题目链接:https://cn.vjudge.net/problem/HDU-6205

题意  给你n堆卡牌,每一堆卡牌有一个花费,当你捡起这一堆卡牌时,手中当前值增加当前堆的数目,然后再减去当前堆的花费

如果手中当前值为负数则  游戏结束

给你一种操作,在游戏开始前  你可以把最左边的卡牌堆 移动到最后面  可以移动任意次。

问最少移动几次 使得获得的牌数  最多。(如果有多个结果,输出最小的移动次数)

思路:由于是 只能从头移动到尾部 则可以先预处理两倍的数组  如下:

5            
4 6 2 8 4
1 5 7 9 2  

变成   

10
4 6 2 8 4 4 6 2 8 4
1 5 7 9 2 1 5 7 9 2

相当于已经把所有的情况移动好,从里面找可以获得最多的卡牌数即可

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define ll long long
const int maxn = 1e6 + 5;
struct node {
    int a,v;
}pos[maxn*2];
int n,cnt,sum,st,ans,m;
int main()
{
    while(~scanf("%d",&n)) {
        for(int i=1;i<=n;i++) {
            scanf("%d",&pos[i].a);
            pos[i+n].a=pos[i].a;
        }
        for(int i=1;i<=n;i++) {
            scanf("%d",&pos[i].v);
            pos[i+n].v = pos[i].v;
        }
        ans=0,cnt=0,sum=0,st=0,m=0;
        for(int i=1;i<=2*n;i++) {
            cnt+=(pos[i].a-pos[i].v);//手中当前值
            sum+=pos[i].a;//获得的卡牌数
            if(ans<sum){//记录最大卡牌数时的最小移动次数
                ans=sum;
                m=st;
            }
            while(cnt<0&&st<i) { //只要手中当前值为负数,就让当前数组最前面的牌堆移动到最后
                st++;
                sum-=pos[st].a;
                cnt-=(pos[st].a-pos[st].v);  
            }
        }
        printf("%d\n",m);
    }

    return 0;
}