题意就不说了,讲起来比较麻烦,需要注意的是操作过程中值只会在-100到100之间变化。
因为是队友读的题,在他讲题意过程中我的思想出现了问题,以为这个-100和100只是输入的限制,过程中并没有限制...然后我的想法就是从后往前模拟,解不等式,通过取交集、并集的方式维护出先手必胜和必败的区间,然后判断m处于哪个区间...(这果断不可做啊QAQ)
直到赛后看题解,看到了-100和100的限制...
好吧,如果值限制在-100到100之间,这题就很好做了。和我理解错题意的部分想法差不多,逆着做,把我想的解不等式改为递推就很简单了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define For(i,a,b) for(int i=a;i<=b;i++)
const int N = 1010;
int n,m,k,l;
int a[N][3];
int dp[N][205];//将-100到100偏移到(0,200)
int main(){
scanf("%d %d %d %d",&n,&m,&k,&l);
For(i,1,n) scanf("%d %d %d",&a[i][0],&a[i][1],&a[i][2]);
For(i,-100,100){//1代表先手胜,0代表平局,-1代表先手负
int j=i+100;
if(i>=k) dp[n+1][j]=1;
else if(i<=l) dp[n+1][j]=-1;
}
int tt=2,t1,t2,t3;//通过tt来判断当前操作是先手做的还是后手做的
if(n&1) tt=1;
for(int i=n;i>=1;i--){
if(tt&1){
For(j,-100,100){
t1=t2=t3=-1;
int kk=j+100;
if(a[i][0]!=0) t1=dp[i+1][min(200,kk+a[i][0])];
if(a[i][1]!=0) t2=dp[i+1][max(0,kk-a[i][1])];
if(a[i][2]!=0) t3=dp[i+1][-j+100];
dp[i][kk]=max(t1,max(t2,t3));
}
}
else{
For(j,-100,100){
t1=t2=t3=1;
int kk=j+100;
if(a[i][0]!=0) t1=dp[i+1][min(200,kk+a[i][0])];
if(a[i][1]!=0) t2=dp[i+1][max(0,kk-a[i][1])];
if(a[i][2]!=0) t3=dp[i+1][-j+100];
dp[i][kk]=min(t1,min(t2,t3));
}
}
tt++;
}
m+=100;
if(dp[1][m]==1) printf("Good Ending\n");
else if(dp[1][m]==0) printf("Normal Ending\n");
else printf("Bad Ending\n");
return 0;
}