题目链接: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;
}