日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LightOJ 1401 No More Tic-tac-toe 博弈论SG打表

發布時間:2024/10/8 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LightOJ 1401 No More Tic-tac-toe 博弈论SG打表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意

玩家和電腦輪流在1*N的矩形內放置棋子,每次只能放一個棋子,相同的棋子不能相鄰 ,玩家先手,最后沒有合法棋子可放的一方敗;現在給你一個殘局狀態,若玩家獲勝,輸出yes,否則輸出No;

分析

首先,題目給定一個殘局,要判斷下一步輪誰下棋;因為每次只能放一個棋子,所以棋子個數是奇數,輪到電腦下棋;

其次,要判斷當前殘局是否是奇異局勢;無論誰遇到奇異局勢,都是必敗的;

SG打表

用一個三維數組表示sg函數:sg[n][i][j]

用 i / j =0表示表示點 "." ,i / j =1表示棋子O,i/j=2表示棋子X,sg[3][1][2]代表中間有三個空的格子,這些格子的左邊是O,右邊是X

對于方格個數為N的情況,可以將棋子X和棋子O放到方格1~N的任意一個格子處,每次分成左右兩堆格子,由于他們是獨立的左右兩堆格子,因此可以異或得出分開后的sg值,最后找出沒有出現過的非負整數即可

暴力打表竟然過了

#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int maxn=109; #define INF 0x3f3f3f3f int sg[maxn][3][3]; bool vis[maxn]; char s[maxn];void SG(){for(int i=1;i<maxn;i++){//枚舉區間長度for(int j=0;j<3;j++){//枚舉左端點for(int k=0;k<3;k++){//枚舉右端點memset(vis,0,sizeof vis);//清空標記for(int pos=1;pos<=i;pos++){//枚舉區間斷點if(!((pos==1&&j==1)||(pos==i&&k==1))){vis[sg[pos-1][j][1]^sg[i-pos][1][k]]=1;}if(!((pos==1&&j==2)||(i==pos&&k==2))){vis[sg[pos-1][j][2]^sg[i-pos][2][k]]=1;}}//不屬于這個集合的最小非負正整數for(int t=0;;t++)if(!vis[t]){sg[i][j][k]=t;break;}}//k}//j}//i } int main(){int T;scanf("%d",&T);int ca=1;SG();while(T--){scanf("%s",s);int len=strlen(s);int num=0,last=0,lc=0,ans=0;for(int i=0;i<len;i++){if(s[i]!='.'){num++;int nowc=(s[i]=='O')?1:2;ans^=sg[i-last][lc][nowc];lc=nowc;last=i+1;}}ans^=sg[len-last][lc][0];printf("Case %d: ",ca++);if(num&1){//奇數,電腦面對的局勢if(ans==0) printf("Yes\n");else printf("No\n");}else{//偶數,玩家面對的局勢if(ans==0) printf("No\n");else printf("Yes\n");}} }

打表代碼

#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int maxn=109; #define INF 0x3f3f3f3f int sg[maxn][3][3]; bool vis[maxn]; char s[maxn];void SG(){for(int i=1;i<maxn;i++){//枚舉長度for(int j=0;j<3;j++){for(int k=0;k<3;k++){memset(vis,0,sizeof vis);for(int pos=1;pos<=i;pos++){//if(!((pos==1&&j==1)||(pos==i&&k==1))){vis[sg[pos-1][j][1]^sg[i-pos][1][k]]=1;}if(!((pos==1&&j==2)||(i==pos&&k==2))){vis[sg[pos-1][j][2]^sg[i-pos][2][k]]=1;}}for(int t=0;;t++)if(!vis[t]){sg[i][j][k]=t;break;}}//k}//j}//i } int main(){SG();printf("............\n");for(int i=1;i<100;i++){printf("%d,",sg[i][0][0]);}printf("\n");printf("O...........\n");for(int i=1;i<100;i++){printf("%d,",sg[i][1][0]);}printf("\n");printf("...........O\n");for(int i=1;i<100;i++){printf("%d,",sg[i][0][1]);}printf("\n");printf("...........X\n");for(int i=1;i<100;i++){printf("%d,",sg[i][0][2]);}printf("\n");printf("X...........\n");for(int i=1;i<100;i++){printf("%d,",sg[i][2][0]);}printf("\n");printf("O.........X\n");for(int i=1;i<50;i++){printf("%d,",sg[i][1][2]);}printf("\n");printf("X..........O\n");for(int i=1;i<50;i++){printf("%d,",sg[i][2][1]);}printf("\n");}

?

AC代碼

#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int maxn=109; #define INF 0x3f3f3f3f char s[maxn]; int SG(int len,int left,int right){if(left==0&&right==0)return (len&1);if(left>0&&right==0||left==0&&right>0)return len;if(left>0&&right>0)return 0; } int main(){int T;scanf("%d",&T);int ca=1;while(T--){scanf("%s",s);int len=strlen(s);int num=0,last=0,lc=0,ans=0;for(int i=0;i<len;i++){if(s[i]!='.'){num++;int nowc=(s[i]=='O')?1:2;//ans^=sg[i-last][lc][nowc];ans^=SG(i-last,lc,nowc);lc=nowc;last=i+1;}}//ans^=sg[len-last][lc][0];ans^=SG(len-last,lc,0);printf("Case %d: ",ca++);if(num&1){//奇數,電腦面對的局勢if(ans==0) printf("Yes\n");else printf("No\n");}else{//偶數,玩家面對的局勢if(ans==0) printf("No\n");else printf("Yes\n");}}return 0; }

?

總結

以上是生活随笔為你收集整理的LightOJ 1401 No More Tic-tac-toe 博弈论SG打表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。