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;
}
}
}
}