【算法总结】博弈论相关

〖相关资料〗

《博弈论 SG函数》

〖相关题目〗

1.【bzoj1188】[HNOI2007]分裂游戏

题意:共有n个瓶子,标号为0,1,2.....n-1,第i个瓶子中装有p[i]颗巧克力豆,两个人轮流取豆子,每一轮每人选择3个瓶子,标号为i,j,k,并要保证i<j,j<=k且第i个瓶子中至少要有1颗巧克力豆。随后这个人从第i个瓶子中拿走一颗豆子并在j,k中各放入一粒豆子(j可能等于k)。如果轮到某人而他无法按规则取豆子,那么他将输掉比赛。问先手必胜策略的第一步方案。

分析:hzwerの博客

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 using namespace std;
 7 int T,n,a[25],sg[25];
 8 bool mark[20000];
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
13     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
14     return x*f;
15 }
16 void pre()
17 {
18     for(int i=2;i<=21;i++)
19     {
20         memset(mark,0,sizeof(mark));
21         for(int j=1;j<i;j++)
22             for(int k=1;k<=j;k++)
23                 mark[sg[j]^sg[k]]=true;
24         for(int j=0;;j++)
25             if(!mark[j]){sg[i]=j;break;}
26     }
27 }
28 int main()
29 {
30     pre();T=read();
31     while(T--)
32     {
33         n=read();
34         for(int i=1;i<=n;i++)a[i]=read();
35         int ans=0,win=0;
36         for(int i=1;i<=n;i++)
37             if(a[i]&1)ans^=sg[n-i+1];
38         for(int i=1;i<=n;i++)
39             for(int j=i+1;j<=n;j++)
40                 for(int k=j;k<=n;k++)
41                     if((ans^sg[n-i+1]^sg[n-j+1]^sg[n-k+1])==0)
42                     {
43                         win++;
44                         if(win==1)printf("%d %d %d\n",i-1,j-1,k-1);
45                     }
46         if(!win)printf("-1 -1 -1\n");
47         printf("%d\n",win);
48     }
49     return 0;
50 }

2.【bzoj1299】[LLH邀请赛]巧克力棒

题意:每次一人可以从盒子里取出若干条巧克力棒,或是将一根取出的巧克力棒吃掉正整数长度。两人轮流,无法操作的人输。 问是否先手必胜。

分析:hzwerの博客

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int T,n,a[15];
 6 bool yes;
 7 int read()
 8 {
 9     int x=0,f=1;char c=getchar();
10     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
11     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
12     return x*f;
13 }
14 void dfs(int deep,int sum,int non)
15 {
16     if(deep==n+1)
17     {
18         if(sum==0&&non)yes=true;
19         return;
20     }
21     dfs(deep+1,sum^a[deep],1);
22     dfs(deep+1,sum,non);
23 }
24 int main()
25 {
26     T=10;
27     while(T--)
28     {
29         n=read();yes=false;
30         for(int i=1;i<=n;i++)a[i]=read();
31         dfs(1,0,0);
32         if(yes)puts("NO");
33         else puts("YES");
34     }
35     return 0;
36 }

3.【bzoj1443】[JSOI2009]游戏Game

题意:见原题。

分析:ONION_CYCの博客

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cmath>
  5 using namespace std;
  6 const int N=105;
  7 const int M=1e4+5;
  8 const int inf=0x3f3f3f3f;
  9 const int xx[4]={0,0,-1,1};
 10 const int yy[4]={-1,1,0,0};
 11 int n,m,id,S,T,cnt=1,tot;
 12 int map[N][N],col[M],ix[M],iy[M],ans[M];
 13 int first[M],cur[M],q[M],dis[M];
 14 bool vis[M];
 15 char s[N];
 16 struct edge{int to,next,flow;}e[M*20];
 17 void insert(int u,int v,int w)
 18 {
 19     e[++cnt]=(edge){v,first[u],w};first[u]=cnt;
 20     e[++cnt]=(edge){u,first[v],0};first[v]=cnt;
 21 }
 22 bool bfs()
 23 {
 24     memset(dis,-1,sizeof(dis));
 25     int head=0,tail=1;
 26     q[head]=S;dis[S]=0;
 27     while(head!=tail)
 28     {
 29         int u=q[head++];
 30         for(int i=first[u];i;i=e[i].next)
 31         {
 32             int v=e[i].to;
 33             if(dis[v]!=-1||!e[i].flow)continue;
 34             dis[v]=dis[u]+1;
 35             q[tail++]=v;
 36         }
 37     }
 38     return dis[T]!=-1;
 39 }
 40 int dfs(int u,int a)
 41 {
 42     if(u==T||a==0)return a;
 43     int f,flow=0;
 44     for(int& i=cur[u];i;i=e[i].next)
 45     {
 46         int v=e[i].to;
 47         if(dis[v]==dis[u]+1&&(f=dfs(v,min(e[i].flow,a)))>0)
 48         {
 49             e[i].flow-=f;e[i^1].flow+=f;
 50             flow+=f;a-=f;if(a==0)break;
 51         }
 52     }
 53     return flow;
 54 }
 55 void DFS(int x,int f)
 56 {
 57     vis[x]=true;
 58     if(col[x]==f&&x!=S&&x!=T)ans[++tot]=x;
 59     for(int i=first[x];i;i=e[i].next)
 60         if(e[i].flow==f&&!vis[e[i].to])
 61             DFS(e[i].to,f);
 62 }
 63 int main()
 64 {
 65     scanf("%d%d",&n,&m);
 66     for(int i=1;i<=n;i++)
 67     {
 68         scanf("%s",s+1);
 69         for(int j=1;j<=m;j++)
 70         {
 71             if(s[j]==‘#‘)continue;
 72             id=(i-1)*m+j;map[i][j]=id;
 73             ix[id]=i;iy[id]=j;
 74         }
 75     }
 76     S=0;T=n*m+1;
 77     for(int i=1;i<=n;i++)
 78         for(int j=1;j<=m;j++)
 79         {
 80             if(!map[i][j])continue;
 81             if((i+j)&1)
 82             {
 83                 insert(map[i][j],T,1);
 84                 continue;
 85             }
 86             col[map[i][j]]=1;
 87             insert(S,map[i][j],1);
 88             for(int k=0;k<4;k++)
 89                 if(map[i+xx[k]][j+yy[k]])
 90                     insert(map[i][j],map[i+xx[k]][j+yy[k]],1);
 91         }
 92     while(bfs())
 93     {
 94         for(int i=S;i<=T;i++)cur[i]=first[i];
 95         dfs(S,inf);
 96     }
 97     DFS(S,1);memset(vis,0,sizeof(vis));DFS(T,0);
 98     if(tot)
 99     {
100         printf("WIN\n");
101         sort(ans+1,ans+tot+1);
102         for(int i=1;i<=tot;i++)
103             printf("%d %d\n",ix[ans[i]],iy[ans[i]]);
104     }
105     else printf("LOSE\n");
106     return 0;
107 }

4.【bzoj3895】取石子

题意:N堆石子排成一排,轮流操作,每次操作时从下面的规则中任选一个:从某堆石子中取走一个,合并任意两堆石子,不能操作的人输。问是否有先手必胜策略。

分析:iamxymの博客

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=50055;
 6 int T,n,x,y,a[55];
 7 bool f[55][N],vis[55][N];
 8 int read()
 9 {
10     int x=0,f=1;char c=getchar();
11     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
12     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
13     return x*f;
14 }
15 bool dfs(int x,int y)
16 {
17     if(vis[x][y])return f[x][y];
18     vis[x][y]=true;
19     if(y==1)return f[x][y]=dfs(x+1,0);
20     if(x-1>=0&&!dfs(x-1,y))return f[x][y]=true;
21     if(x-2>=0&&!dfs(x-2,y+2+(y>0)))return f[x][y]=true;
22     if(y-1>=0&&!dfs(x,y-1))return f[x][y]=true;
23     if(x-1>=0&&y&&!dfs(x-1,y+1))return f[x][y]=true;
24     return false;
25 }
26 int main()
27 {
28     T=read();
29     while(T--)
30     {
31         n=read();x=0;y=0;
32         for(int i=1;i<=n;i++)
33         {
34             a[i]=read();
35             if(a[i]==1)x++;
36             else y+=a[i]+1;
37         }
38         if(y)y--;dfs(x,y);
39         if(f[x][y])puts("YES");
40         else puts("NO");
41     }
42     return 0;
43 }

5.【bzoj3105】[cqoi2013]新Nim游戏

题意:见原题。

分析:ONION_CYCの博客

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 using namespace std;
 6 int n,p[30],a[105],c[105];
 7 LL ans;
 8 int read()
 9 {
10     int x=0,f=1;char c=getchar();
11     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
12     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
13     return x*f;
14 }
15 int main()
16 {
17     n=read();
18     for(int i=1;i<=n;i++)a[i]=read();
19     sort(a+1,a+n+1);
20     for(int i=1;i<=n;i++)c[i]=a[i];
21     for(int i=n;i>=1;i--)
22     {
23         for(int j=30;j>=0;j--)
24         {
25             if(!(a[i]&(1<<j)))continue;
26             if(!p[j]){p[j]=a[i];break;}
27             a[i]^=p[j];
28         }
29         if(!a[i])ans+=c[i];
30     }
31     printf("%lld",ans);
32     return 0;
33 }

原文地址:https://www.cnblogs.com/zsnuo/p/8521364.html

时间: 2024-11-11 00:02:23

【算法总结】博弈论相关的相关文章

算法—二叉查找树的相关一些操作及总结

二叉查找树得以广泛应用的一个重要原因就是它能够保持键的有序性,因此它可以作为实现有序符号表API中的众多方法的基础.这使得符号表的用例不仅能够通过键还能通过键的相对顺序来访问键值对.下面,我们要研究有序符号表API中各个方法的实现. 1.最大键和最小键 如果根结点的左链接为空,那么一棵二叉查找树中最小的键就是根结点:如果左链接非空,那么树中的最小键就是左子树中的最小键.简单的循环也能等价实现这段描述,但为了保持一致性我们使用了递归.找出最大键的方法也是类似的,只是变为查找右子树而已. 2.向上取

图像处理基本算法-卷积和相关

在执行线性空间滤波时,经常会遇到两个概念相关和卷积二者基本相似,在进行图像匹配是一个非常重要的方法.相关是滤波器模板移过图像并计算计算每个位置乘积之和的处理卷积的机理相似,但滤波器首先要旋转180度相关的计算步骤:(1)移动相关核的中心元素,使它位于输入图像待处理像素的正上方(2)将输入图像的像素值作为权重,乘以相关核(3)将上面各步得到的结果相加做为输出卷积的计算步骤:(1)卷积核绕自己的核心元素顺时针旋转180度(2)移动卷积核的中心元素,使它位于输入图像待处理像素的正上方(3)在旋转后的卷

算法——查找排序相关面试题和leetcode使用

1.给两个字符串s和t,判断t是否为s的重新排列后组成的单词. s = "anagram", t = "nagaram", return true. s = "rat", t = "car", return false. leetcode地址:https://leetcode.com/problems/valid-anagram/description/ (1)解法一:排序,O(n*logn) class Solution:

用蒙特卡洛算法解概率相关的路线规划问题

写给小陈~ 参考文献: Chou X., Gambardella L.M., Montemanni R. (2018) Monte Carlo Sampling for the Probabilistic Orienteering Problem. In: Daniele P., Scrimali L. (eds) New Trends in Emerging Complex Real Life Problems. AIRO Springer Series, vol 1. Springer -

博弈论相关(巴什博弈)

巴什博奕 基本模型:有n个石子,两人轮流取,一次取1-m个,先取完者胜. 另一种描述:两人每次竞价,加价只能在1-m范围中,价格先达到或超过n元者胜. 解决方法:n%(m+1)==0,后手胜,否则先手胜.          例题: hdu 2897 邂逅明下        题目描述(简略版):有n个石子,两人轮流取,一次取p-q个,先取完者输.        把问题转变为巴什博弈,写成n=(q+p)*k+r的形式,讨论即可       1 #include<bits/stdc++.h> 2 3

算法相关概述

算法概述 从字面意义上理解,算法(Algorithm)就是用于计算的方法,并通过这种方法可以达到预期的计算结果.算法的专业解释:算法是解决实际问题的一种精确描述的方法,算法是对特定问题的求解步骤的一种精确描述方法.但更广泛认可的算法专业定义:算法是模型分析的一组可行的.精确的和有穷的规则. 通俗的讲,算法可以理解为一个完整的解题步骤,由一些基本运算和规定的运算顺序而构成.通过这样的解题步骤可以解决特定的问题.从计算机程序设计的角度看,算法由一系列求解问题的指令构成,能够根据规范的输入,在有限的时

【算法总结】根号算法相关

[莫队算法] [相关资料] <[莫队算法]> [相关题目] 1.[bzoj2038][2009国家集训队]小Z的袜子(hose) 题意:给出n个数与m个区间,在每个区间内选出两个数,求选出的两个数相等的概率. 分析:hzwerの博客 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #define LL long long 6 usin

【基础操作】博弈论详解

博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子) 先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 模板题(Nim 游戏) 有 $n$ 堆石子,两个人轮流从任意一堆石子中取出正整数个石子,取不了的一方输.问先手是否有必胜策略. 题解 经典的博弈论模板题. 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/game_theory.html

写在前面:21天学习算法

最近打算找一份新的工作,感到自己在算法环节还很疲弱.由于时间还算充裕,就决定将LeetCode上面的算法题学一遍,找出自己的薄弱,锻炼算法思维,吸收他人长处.个人觉得,刷题只是学习算法中的一个环节,主要的作用是用来反馈错误和增加熟练度.相比较刷题,更加重要的是对比和总结,对比自己的代码和他人的代码,对比不同的解法,总结一类算法或一类问题,总结一些tips,这两步是提升自己的关键.另外,为了不让自己的视野过于局限,让得到的碎片化学习成果体系化,可以在刷题的时候,就某方面的算法或数据结构,多参考其他