POJ 2960 S Nim(SG 記憶化搜尋)

2021-07-04 17:43:11 字數 1589 閱讀 5468

題目大意:在尼姆遊戲的基礎上,把能夠取的石頭個數限定了。用sg函式實現,每個計算出的sg值都等價於原尼姆遊戲中的一堆的石子數。

某一堆的石子數取走一定數量k後可以得到乙個新石子堆對應的sg值,也就是原石堆的所有分支的其中乙個。

這時候後手可以根據實際情況處理。sg值是子分支中沒有出現過的最小整數。

比如 原sg = 3的分支有sg = 0, sg = 1, sg = 2,那麼只要滿足sg的異或值為0,必定有另外乙個sg=3,只需要將其也變成對方所變成的分支即可。

又如原sg = 3的分支有sg = 0, sg = 1, sg = 2,sg =  4……sg=k,而另外乙個sg=3的分支為sg = 0, sg = 1, sg = 2。對方把3變成了k(k>3),而我方只要把k再變回3就可以了。這樣仍是成對存在了。

為什麼用dp打表wa了,沒找到問題,以後還是用記憶化搜尋吧,時間複雜度一樣的,也可能是我細節寫的不對。

#include#include#include#include#includeusing namespace std;

const int maxn = 100;

int match[maxn + 5];

int h[maxn + 5];

int sg[maxn * maxn + 5];

int m, l, k;

int dfs(int p)

bool vis[maxn*maxn+5] = ;

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

}for (int i = 0; ; i ++)

}}int main()

scanf("%d", &m);

char ans[maxn + 5];

memset(sg, -1, sizeof(sg));

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

int res = 0;

/** dfs */

sg[0] = 0;

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

res ^= sg[h[i]];

}/** dp */

// sort(match, match + k);

// memset(sg, 0, sizeof(sg));

// bool _hash[maxn * maxn + 5] = ;

// int mx = *max_element(h, h + l);

// for (int i = 0; i <= mx; i ++)

// for (int j = 0;; j ++)

// }

// }

// for (int i = 0; i < l; i ++)

ans[i] = res ? 'w':'l';

}ans[m] = 0;

puts(ans);

}return 0;

}

POJ 2960 典型的sg函式

這道題之前做過的,但是晚上拿出來熟悉一下!但是runtime error!很奇怪,查!堅決不看之前的 後來突然乙個念頭 會不胡hash陣列沒有初始化!加了個hash 110 a了,忘記的是定義為全域性性質的陣列才會被編譯器自動初始化為0 非全域性的不會自動初始化!哎哎!教訓。poj 2960 res...

POJ2960 SG函式,模板題

題目大意 已知一次可拿個數的種類 求出先手是否勝利,若勝利輸出w否則輸出l sg函式模板 include const int n 10008 int a 110 sg n f n void sgt int a,int y,int z 題目 include include const int n 10...

POJ2960 S Nim(博弈論 sg函式)

題意 給出一系列石子堆,現在每次只能從乙個堆中拿出固定石子數,問輸贏結果。要點 跟nim博弈很像,但是這次每次只能拿固定個數,所以要用sg函式,下面是sg函式的具體定義 sg x mex sg y y是x的後繼結點 其中mex x x是乙個自然是集合 函式是x關於自然數集合的補集中的最小值,比如x ...