题目:
输入例子1:
1
5 3
2 2 3 3 1
输出例子1:
YES
输入例子2:
1
5 2
0 0 1 2 1
输出例子2:
NO
说明:
起初,我理解错了题意,以为只能一次拿一个,放一个。后来发现,题意相当是,你从第一堆积木开始,每次可以执行三种操作,即走,拿,放。而若选择走,则不能返回上一堆进行拿放操作,若选择拿放可以一直拿放直到想走了为止。
做法:
那么,保持序列是一个严格递增的序列,即最优的序列一定是0,1,2,3,4,5,6,…这样的。只要最后能满足此序列,就代表可以完成任务。即第一堆积木,直接拿完就好了。其他的对于当前的第i堆积木,若它的数量大于前一堆,则拿走多余积木,使它的数量刚好比前一堆的大1就好了。反之,则在背包中积木数量足够的时候,拿出积木放在这一堆上,使得它数量比前一堆大1,若此时出现背包中积木数量不足够,则说明任务无法完成。
代码:
#include<bits/stdc++.h>
#define int long long //定义int为longlong,方便使用(因为习惯性都会定义int变量,这样可以减少错误出现的概率)
using namespace std;
const int maxn=1e5+5;
signed main(){ //由于上面将longlong改成了int,所以这里不能再使用int main,需要使用signed main
int t;
cin>>t;
while(t--){
int n,m;
int a[maxn];
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a[i];
}
bool flag=true;
for(int i=0;i<n;i++){
if(i==0){
m+=a[i];
a[i]=0;
}else if(i>0&&a[i]>a[i-1]){
int x=a[i]-a[i-1]-1;
m+=x;
a[i]-=x;
}else if(i>0&&a[i]<=a[i-1]){
int x=a[i-1]-a[i]+1;
if(m>=x){
m-=x;
a[i]+=x;
}else{
flag=false;
break;
}
}
}
if(flag){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
return 0;
}