取石子遊戲

2022-02-27 07:43:31 字數 1689 閱讀 9238

也許更好的閱讀體驗

設\(f[i][j][k]\)表示三堆石子分別為\(i,j,k\)個石子時先手必勝還是先手必敗\(1\)為必勝\(0\)為必敗

由於石子的位置沒有影響,所以\(f[i][j][k]=f[i][k][j]=f[j][i][k]=f[j][k][i]=f[k][i][j]=f[k][j][i]\)

當一種狀態可以轉移成先手必敗態時,該狀態是先手必勝態

很明顯,只要轉移到先手必敗態,那麼對面就必敗了

所以我們列舉後繼狀態然後看能不能轉移到先手必敗態,如能即為必勝態,否則就是必敗態

再加點優化什麼的

若\(f[i][j][k]\)是必敗態,那麼\(f[i][j][k+a] (a>0)\)就是必勝態(當然\(a<0\)也都是必敗態,但是對演算法沒什麼用處)

證明,若\(a>0\),先手可以對\(k\)拿走\(a\)個石子就轉移到必敗態

那麼我們先全部賦值為必勝態,然後當我們找到乙個必敗態後即可\(break\)

用乙個f[i][j]表示有沒有兩堆石子數為\(i,j\)的必敗態,如列舉到的石子堆包含了包含了\(i,j\)即可\(break\)

另外,可對包含乙個為\(0\)的資料特殊對待,下面沒有給出**

下面是主要**

int f[303][303];

int g[303][303][303];

memset(f,1,sizeof(f));

f[0][0][0]=0,g[0][0]=1;

for (int i=0;i<=100;++i)

for (int j=i;j<=100;++j)

f[i][k][j]=f[j][i][k]=f[j][k][i]=f[k][i][j]=f[k][j][i]=f[i][j][k];

if (!f[i][j][k])}}

} }

上面的複雜度是\(o(n^4)\),因為去列舉後繼狀態會列舉到非常多的重複狀態,所以我們考慮由必敗態反推必勝態

這樣重複的狀態就大大減少了,複雜度為\(o(n^3)\)多一點

/*******************************

author:morning_glory

lang:c++

created time:2023年06月10日 星期一 09時35分36秒

*******************************/

#include #include #include using namespace std;

const int maxn = 303;

//}cin;

//}}}

int t,x,y,z;

bool f[maxn][maxn][maxn];

inline void update (int a,int b,int c)

int main()

while (t--)

return 0;

}

取石子遊戲

如下 include include intmain k b a temp floor k 1.0 sqrt 5 2.0 if temp a printf 0 n else printf 1 n return 0 一 巴什博奕 bash game 只有一堆n個物品,兩個人輪流從這堆物品中取物,規定每...

取石子遊戲

有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子 二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。in...

取石子遊戲

取石子遊戲 time limit 1000ms memory limit 10000k total submissions 25176 accepted 7961 description 有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆...