2018ACM/ICPC徐州网络赛B BE, GE or NE

题目链接

题意就不说了,讲起来比较麻烦,需要注意的是操作过程中值只会在-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;
}

猜你喜欢

转载自blog.csdn.net/qq_38515845/article/details/82595342