1. 程式人生 > >海盜分金問題(博弈)

海盜分金問題(博弈)

for log fine using ble 規律 vector printf 問題

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 }

海盜分金問題(博弈)