hdu 6205 card card card
https://vjudge.net/contest/184514#problem/L
题意:
排成一行的一堆牌,每堆牌都有一定数量的牌,然后每堆牌对应有一个惩罚值。一开始所有的牌都是正面向下的,并且在游戏开始之前可以把第一堆牌移到最后,这个操作可以进行若干次。在那之后,一个人开始依次拿起一堆牌,并且把它们全部正面朝上,之后需要把某些牌翻转到正面向下,翻转的数量就是这堆牌的惩罚值,之后把正面向上的牌翻转加到下一堆进行操作。当遇到当前的正面向上的牌小于当前的牌的惩罚值的时候,游戏结束,可以得到这堆牌以及之前的所有牌。
问需要挪多少堆到后面可以得到最大数量的牌。
思路:
一开始被题解误导,wa了6发。首先这题由于要挪到后面,而且有顺序,所以很自然的想到复制一份加到后面,形成一个环,这样方便许多。之后我们设置3个变量,一个表示当前取得的牌数num,一个表示当前减去惩罚值之后剩下的牌sum,一个记录当前取得堆的数量cnt。当cnt >= n的时候,就说明我们可以取到全部,也就是取到最多的了,记录位置并跳出。当sum < 0 的时候,就说明不能再取了,此时就更新num的值并记录此时的位置,将cnt和sum重置为0.循环完之后所求的num就是最大值。
当我们记录的位置ans最后要减去n,因为我们是讲题中所给的线拼成了一个环,所以位置会有偏移。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 4 int a[2000005]; 5 int b[2000005]; 6 7 int main() 8 { 9 int n; 10 11 while (scanf("%d",&n) != EOF) 12 { 13 for (int i = 1;i <= n;i++) 14 { 15 scanf("%d",&a[i]); 16 a[i+n] = a[i]; 17 } 18 19 for (int i = 1;i <= n;i++) 20 { 21 scanf("%d",&b[i]); 22 b[i+n] = b[i]; 23 } 24 25 long long pre = 0; 26 long long sum = 0; 27 long long num = 0; 28 long long maxx = -1e12; 29 int ans = 0; 30 int cnt = 0; 31 32 for (int i = 1;i < 2 * n;i++) 33 { 34 num += a[i]; 35 36 sum = (pre + a[i] - b[i]); 37 38 39 if (sum >= 0) 40 { 41 cnt++; 42 pre = sum; 43 } 44 else 45 { 46 if (num > maxx) 47 { 48 maxx = num; 49 ans = i; 50 } 51 52 pre = 0; 53 cnt = 0; 54 } 55 56 if (cnt >= n) 57 { 58 ans = i; 59 break; 60 } 61 } 62 63 if (ans == n) printf("%d\n",0); 64 else printf("%d\n",ans - n); 65 } 66 67 68 return 0; 69 }
康复训练中~欢迎交流!