HDU 6205 前缀和

来源:互联网 发布:qq三国自动打怪源码 编辑:程序博客网 时间:2024/06/11 11:20

题目

card card card

题意

有 n 堆卡片,每堆都有一定数量卡片和一个惩罚值,在游戏开始前可以把第一堆移到最后面。每搬一堆卡片,会增加和该堆卡片数量相等的分数,但是会减去惩罚值,当分数为负或全搬完则结束比赛。问怎么才能在移动最少堆卡片的情况下搬尽量多的卡片。(惩罚值总数和卡片总数是相等的)

题解

前缀和。因为惩罚值和卡片总数是相同的,所以最多移动 (n-1) 次,就能保证拿走所有卡片。
先假设从第一堆开始拿,如果在拿的过程中,总分变成负数,则把该堆及之前的所有堆按顺序移到末尾。然后从下一堆开始重复此过程,一遍循环后一定能得出答案。
在处理的过程中用上前缀和,就可以把时间复杂度将为 O(n)。

代码

#include <algorithm>#include <bitset>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <climits>#include <iostream>#include <list>#include <map>#include <queue>#include <set>#include <stack>#include <string>#include <vector>using namespace std;const int MAX = 1000005;int a[MAX],b[MAX];int sum[MAX];int main(){    int n;    while(cin >> n){        for(int i=0;i<n;++i){            scanf("%d",a + i);        }        for(int i=0;i<n;++i){            scanf("%d",b + i);        }        memset(sum,0,sizeof(sum));        sum[0] = a[0] - b[0];        for (int i = 1; i < n; ++i) {            sum[i] = (sum[i-1] + a[i] - b[i]);        }        int pre = -1;        for(int i=0;i<n-1;++i){            if(pre == -1){                if(sum[i] < 0)                    pre = i;            }            else if(sum[i] - sum[pre] < 0){                pre = i;            }        }        cout << pre + 1 << endl;    }    return 0;}
原创粉丝点击