题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4524
一开始看题目,以为很难,其实是自己吓唬自己.....
题目有句话要特别注意:如果右边没有箱子或者右边的箱子已经消失了,则无法操作当前的箱子,这是解题的关键!根据这个条件,比较序列中紧挨着的前后两个数(假设是i、j,j=i+1),要分三种情况讨论:1、相等(a[i] = a[j])。这时,两个数都变成0,下一个操作数是a[j]的下一个数,也就是i+2的位置 2、a[i] > a[j],此时肯定不符合题目条件,因为在当前箱子还没消失但右边箱子已经消失的情况下,是无法操作当前箱子的,此时最后肯定有箱子存在。 3、a[i]<a[j]。这时后一个箱子a[j]被点击的数字会改变,此时a[j]里的数要被覆盖。
有两个细节让我wa了几次:1、i 的结束标志最好是n-2,这样的j(j=i+1)不用每次处理都要判断是否越界。(如果是i=n-1,会多了很多繁琐的判断) 2、当序列中的最后两个数相等的时候(例如(1、2、3、4、2),最后会变成(0,0, 0,2,2)),此时由于执行了a[i] = a[j]这个条件里面的操作i++,不会执行a[j] > a[i],此时a[j]不会被新的次数(a[j]-a[i] = 0)覆盖,也就是说a[j] != 0,但是明显这样是可以消去所有的箱子的!!所以a[i] = a[j]里面要加特判,a[j]要设为0。如果不是这种情况,即序列中的最后的一个数a[j] != 0,说明不能消去所有箱子。具体代码如下:
1 #include <iostream> 2 using namespace std; 3 4 const int MAXN = 1000000 + 5; 5 int a[MAXN]; 6 7 int main() 8 { 9 int T, i, j, n, flag; 10 while (cin >> T) 11 { 12 while (T--) 13 { 14 cin >> n; 15 for (i = 0; i < n; i++) 16 cin >> a[i]; 17 flag = 1; 18 for (i = 0; i < n-1; i++) 19 { 20 j = i+1; 21 if (a[i] > a[j]) 22 { 23 flag = 0; 24 break; 25 } 26 else if (a[i] == a[j]) 27 { 28 i++; //再结合外循环的i++,实质上下一次操作的位置是i+2
29 a[j] = 0; //关键1,为了处理序列中最后两个数相同的情况 30 } 31 else 32 { 33 a[j] = a[j] - a[i]; 34 } 35 } 36 if (a[j]) //关键2,也是为了处理序列中最后两个数相同的情况 37 flag = 0;//序列中最后一个数不为0,说明不能消去所有箱子
38 if (flag) 39 printf("yeah~ I escaped ^_^\n"); 40 else 41 printf("I will never go out T_T\n"); 42 } 43 } 44 return 0; 45 }