hdu_5724_Chess(組合博弈)

題目鏈接:hdu_5724_Chess

題意:

給你一個n行20列的棋盤,棋盤裏面有些棋子,每個棋子每次只能往右走一步,如果右邊有棋子,可以跳過去,前提是最右邊有格子,如果當前選手走到沒有棋子可以走了,那麼就算輸,問你先手是否會贏

題解:

一看就知道是組合博弈的問題,關鍵在於如果求SG值,這裏要把一行看成一個狀態,然後根據SG值的定義去求,如果不知道SG的求法,那去找度娘吧。預處理出一行所有狀態的SG,然後對每一行異或一下就行了。

#include<cstdio>
#include<cstring>
#define F(i,a,b) for(int i=a;i<=b;i++)
int sg[1<<20];

void init(){
	int end=(1<<20)-1;
	F(i,0,end){
		int last=-1,h[25],now=0;
		memset(h,-1,sizeof(h));
		F(j,0,19){//枚舉下一步能達到的狀態
			if(i<(1<<j))break;
			if(!((i>>j)&1))last=j;
			if(((i>>j)&1)&&~last)h[sg[i^(1<<j)^(1<<last)]]=1;
		}
		while(~h[now])now++;
		sg[i]=now;
	}
}

int main(){
	init();
	int t;
	scanf("%d",&t);
	while(t--){
		int n,ans=0,tp,ttp;
		scanf("%d",&n);
		F(i,1,n){
			scanf("%d",&tp);
			int now=0;
			F(j,1,tp)scanf("%d",&ttp),now^=1<<(20-ttp);
			ans^=sg[now];
		}
		if(ans)puts("YES");else puts("NO");
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章