博弈论
来源:互联网 发布:威锋认证的淘宝店 编辑:程序博客网 时间:2024/04/18 23:37
1、水题,裸的纳什博弈。
HDU 1846
用推导做出的,比如一次最多取k个石子,总共有n个石子,那么剩下石子数为1-k时,取的人必赢,但剩下k+1的时候,根据最优策略的原则,
那么此时取的人必输,由此可以推导剩下k+1个石子的时候,这个人可以使得石子变成1-k个,由于全部是必胜点,所以这个人无论怎么取都是输,
当取1-k个石子时,这些石子存在必败点时,这个点就是必胜的,如果取后无法达到必败点,这个点就是必败点,由此推可得:
#include<iostream>#include <stdio.h>#include <string.h>#include<stdlib.h>#include <map>#include <set>#include <queue>#include <math.h>#include <algorithm>#include <vector>using namespace std;int q1[5000];int main(){ //freopen("in.txt","r",stdin); int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m; cin >> m; while(m--){ cin >> n >> k; memset(q1,0,sizeof(q1)); for(i=1;i<=k;i++) q1[i]=1; //1-k全部是必胜 for(i=k+1;i<=n;i++){ t1=0; for(j=1;j<=k;j++) if(q1[i-j]==0)t1=1; if(t1==1) q1[i]=1; else q1[i]=0; } if(q1[n]==1) cout << "first" <<endl; else cout << "second" <<endl; } return 0;}第二种做法就是,先手的人一直使后手的人处于必败点,也就是比如k为3,n为15,就把15分成4,4,4,3,这样每次根据对手拿的数量,使得拿的数量正好为一堆,让对手一直处于必败点,那么就可以赢了。
也就是n%(k+1)==0为先手必输,其他都为先手必赢。
#include<iostream>#include <stdio.h>#include <string.h>#include<stdlib.h>#include <map>#include <set>#include <queue>#include <math.h>#include <algorithm>#include <vector>using namespace std;int q1[5000];int main(){ //freopen("in.txt","r",stdin); int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,n,m; int T; cin >> T; while(T--){ cin >> n >> k; if(n%(k+1)==0){ //n%k+1和 n%(k+1)是不一样的 cout << "second" <<endl; }else{ cout << "first" <<endl; } } return 0;}
威佐夫博弈:
有两堆物品,一个人可以取一堆任意多/2堆中取同样多的数量,每次至少取1个,最先取完者获胜。
当一个人面对一个局势如(0,0)(1,2) (3,5)称之为奇异局势,也就是必败的局势bk=ak+k;ak是指在之前没有出现过的最小自然数。
(4,7)(6,10)等等都是奇异局势。
任何操作都可以将奇异局势变成非奇异局势,如果2个值同时减少,其差值必定不可能是其他奇异局势的差。
如果只减少1个,那么这个奇异局势的差值改变了,也就不是奇异局势了。
那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:
ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,...,n 方括号表示取整函数)
奇妙的是其中出现了黄金分割数(1+√5)/2 = 1。618...,因此,由ak,bk组成的矩形近似为黄金矩形,由于2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那么a = aj,bj = aj + j,若不等于,那么a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那么就不是奇异局势。然后再按照上述法则进行,一定会遇到奇异局势。
判断是否为奇异模式:”
while(cin >> a >> b){j=a*(sqrt(5)-1)/2;a1=j*(sqrt(5)+1)/2;a2=(j+1)*(sqrt(5)+1)/2;if(a==a1)cout << "b= " << a+j<<endl;else if(a==a2)cout << "b= " << a+j+1 << endl;elsecout << "不是奇异模式的a" << endl; if(a==a1&&a+j==b||((a+j+1==b)&&(a==a2)))cout << "是" <<endl;elsecout <<"不是"<< endl;}hdu 2177
输入为2个石子,0 0 结束
输出也有若干行,如果最后你是败者,则为0,反之,输出1,并输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。如果在任意的一堆中取走石子能胜同时在两堆中同时取走相同数量的石子也能胜,先输出取走相同数量的石子的情况.
#include<iostream>#include<math.h>using namespace std;int a[1000000][2];int temp=1000000;int temp3=0;void find(){ int temp2=0; while(temp2<=temp){ a[temp3][0]=int(temp3*(1+sqrt(5))/2); a[temp3][1]=a[temp3][0]+temp3; temp2=a[temp3][1]; temp3++; } // cout<<temp3<<endl; }int main(){ find(); int n1,n2; while(cin>>n1>>n2){ if(n1==0&&n2==0) break; double tempor=(sqrt(5)+1)/2; if(n1==(int)((n2-n1)*tempor)){ cout<<"0"<<endl; continue; } cout<<"1"<<endl; int i=0; int sub=n2-n1; if(n1==n2){ cout<<"0 0"<<endl; } else if(((n1-a[sub][0])==(n2-a[sub][1]))&&((n1-a[sub][0])>0)&&((n2-a[sub][1])>0)) cout<<a[sub][0]<<" "<<a[sub][1]<<endl; for(int j=0;j<temp3;j++){ if(a[j][0]==n1){ cout<<a[j][0]<<" "<<a[j][1]<<endl; } if(a[j][1]==n1){ cout<<a[j][0]<<" "<<a[j][1]<<endl; break; } } } return 0; }
HDU 2516
取石子游戏
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5157 Accepted Submission(s): 3116
参看Sample Output.
213100000
Second winSecond winFirst win
SG函数:
Good Luck in CET-4 Everybody!
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9685 Accepted Submission(s): 6275
“升级”?“双扣”?“红五”?还是“斗地主”?
当然都不是!那多俗啊~
作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:
1、 总共n张牌;
2、 双方轮流抓牌;
3、 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4、 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢?
当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。
Good luck in CET-4 everybody!
13
KikiCici
#include <iostream>#include <string.h>#include <math.h>#include <stdio.h>#include <vector>#include <algorithm>#include <map> using namespace std;int sg[1050];int arr[20];int mex(int x){if(sg[x]!=-1)return sg[x];bool vis[1050];int i;memset(vis,0,sizeof(vis));for(i=0;i<10;i++){int temp=x-arr[i];if(temp<0)break;int res=mex(temp);vis[res]=1;}for(i=0;i<1050;i++)if(!vis[i]){sg[x]=i;//cout << x << "--- " << i << endl;break;}return sg[x];}int main(){//freopen("in.txt","r",stdin);int i,j,k,f1,f2,f3,f4,t4,t1,t2,t3,n,m;int T,r,c;memset(sg,-1,sizeof(sg));arr[0]=1;sg[0]=0;for(i=1;i<=10;i++)arr[i]=arr[i-1]*2;while(cin >> n){if(!mex(n))cout << "Cici" << endl;else cout << "Kiki" << endl; }return 0;}
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 【博弈论】
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 博弈论
- 数字旋转方阵 分治法
- 历届试题 打印十字图 (蓝桥杯)
- UVA
- jQuery的应用
- c语言中关于数组的一些基本运算
- 博弈论
- SSL2295 暗黑破坏神(dp)
- 自篡改Dalvik字节码delta.apk原理
- java io
- Caused by: java.lang.UnsupportedOperationException: Can't convert to color: type=0x1
- 【c/c++】如何调用【Window】cmd命令行命令并获取命令行的输出内容
- Android中大图片的处理(一)之图片存在形式
- 建立一个矩阵类Matrix,存储一个4*4的矩阵并能在矩阵中查找某数。要求如下:
- android系统里的配置文件如何生效