1、poj 1067 威佐夫博弈(取石子問題)
課件上的例題,P態和N態與黃金分割點有關。
(0,0) (1,2) (3,5) (4,7) ... P(必敗態)
滿足 a = i*(sqrt(5.0)+1)/2; b = a + i; (a < b)
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int main() {
ll a , b , i;
while(~scanf("%lld%lld",&a,&b)) {
ll t;
if(a > b) {
t = a;
a = b;
b = t;
}
if(floor((b-a)*(sqrt((double)5)+1)/2) == a) printf("0\n");
else printf("1\n");
}
}
2、poj 2234 Nim博弈
滿足Nim和爲0的狀態是必敗態
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main() {
int M , ans;
while(~scanf("%d",&M)) {
int n;
scanf("%d",&n);
ans = n;
M--;
while(M--) {
scanf("%d",&n);
ans = n^ans;
}
if(!ans) printf("No\n");
else printf("Yes\n");
}
}
3、poj 2484 對稱博弈題意:有一圈硬幣,一次只能拿一個或者拿相鄰的兩個,Alice先拿Bob後拿,給出n個硬幣誰最後拿走剩下的硬幣誰贏
當n<3的時候顯然先手贏,當n>=3時後手贏,把這個圈用軸對稱來看,不管先手拿一個或者兩個,後手都可以拿一個或者兩個繼續把硬幣拆成對稱的兩堆,最後一定是後手拿走最後的硬幣
#include<iostream>
#include<cstdio>
using namespace std;
int main() {
int n;
while(cin>>n) {
if(!n) break;
if(n<3)
printf("Alice\n");
else
printf("Bob\n");
}
}
4、poj 1704 Nim階梯博弈
階梯博弈詳解:階梯博弈
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int main() {
int a[1010] , b[1010];
int T , n , i , ans;
cin>>T;
while(T--) {
cin>>n;
for(i = 0 ; i < n ; i ++)
scanf("%d",&a[i]);
sort(a , a + n);
for(i = n - 1 ; i >= 1 ; i --)
b[i] = a[i] - a[i-1] - 1;
b[0] = a[0];
ans = 0;
for(i = n-1 ; i >= 0 ; i -= 2) //注意階梯的方向!!!!
ans = ans^b[i];
if(!ans) printf("Bob will win\n");
else printf("Georgia will win\n");
}
}
5 、從後向前推的博弈
詳解:http://www.cnblogs.com/rainydays/archive/2011/09/07/2169471.html
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int main() {
ll left , right , n;
while(~scanf("%lld",&n)) {
while(1) {
n = ceil(n/9.0); //前一個必勝態的最小數
if(n == 1) {
printf("Stan wins.\n");
break;
}
n = ceil(n/2.0);
if(n == 1) {
printf("Ollie wins.\n");
break;
}
}
}
}