海盗分金问题(博弈)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了海盗分金问题(博弈)相关的知识,希望对你有一定的参考价值。
NBUOJ 2680:海盗分金
题意:
有N个海盗要分M金币,将N个海盗从1-N编号,由第一个人提出分配方案,一人一票(分配者也拥有一票),超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,接下来由下一人分配,以此类推。
分析:从3个人的状态往后推,每次处理出当前分配方案下的被分到0,1 金币的海盗数量,当前被分到0,下次并然分到1,当前分到1的判断是否需要分配2才能满足通过条件,最后输出分配剩余的金币数即可。
代码:
1 #include "cstdio" 2 #include "algorithm" 3 #include "string" 4 #include "cstring" 5 #include "queue" 6 #include "cmath" 7 #include "vector" 8 #include "map" 9 #include "set" 10 #include "stack" 11 #define db double 12 #define inf 0x3f3f3f 13 typedef long long ll; 14 using namespace std; 15 const int N=1e3+5; 16 stack<int> s; 17 int a[3],b[3]; 18 int main() 19 { 20 int n,m; 21 while(scanf("%d%d",&n,&m)==2) 22 { 23 if(n==1) printf("%d\n",m); 24 else if(n==2) puts("0"); 25 else if(n==3) printf("%d\n",m); 26 else 27 { 28 a[0]=2; 29 int ans=0,sum,v,t; 30 for(int i=4;i<=n;i++){ 31 sum=m; 32 ans=i/2; 33 v=min(ans,a[0]); 34 ans-=v,sum-=v; 35 if(!ans){ 36 b[1]=v; 37 b[0]=(i+1)/2-1; 38 a[1]=b[1]; 39 a[0]=b[0]; 40 memset(b,0, sizeof(b)); 41 continue; 42 } 43 t=min(ans,a[1]); 44 ans-=t,sum-=t*2; 45 if(!ans){ 46 b[1]=v; 47 b[0]=(i+1)/2-1; 48 b[2]=t; 49 a[1]=b[1]; 50 a[0]=b[0]; 51 a[2]=b[2]; 52 memset(b,0, sizeof(b)); 53 continue; 54 } 55 } 56 printf("%d\n",sum); 57 } 58 } 59 return 0; 60 }
代码二:
打表之后得到规律:
1 #include "cstdio" 2 int main() 3 { 4 int n,m; 5 while(scanf("%d%d",&n,&m)==2) 6 { 7 if(n==1||n==3) printf("%d\n",m); 8 else if(n==2) puts("0"); 9 else if(n==4) printf("%d\n",m-2); 10 else if(n==5) printf("%d\n",m-3); 11 else printf("%d\n",m-3-(n-4)/2); 12 } 13 return 0; 14 }
以上是关于海盗分金问题(博弈)的主要内容,如果未能解决你的问题,请参考以下文章