Mastermate官网 香港|英国|新加坡|澳大利亚|澳门|深圳硕士研究生申请平台

暑假培训之又见博弈~~7月8号 难度加深

    博弈的问题:博弈 主要注意两种   1:状态  2:最优策略  每个博弈都要注意这两种策略  存在好多种博弈都是这三种博弈的变型,一种是威佐夫博弈,二是巴什博弈,三是尼姆博弈,下面这两道题是尼姆博弈的变形:

poj:  http://poj.org/problem?id=1704  阶级博弈:

这种是 尼姆博弈的一种变型。 主要方式有两点:

1 :两个两个分成一组,这样就可以保持状态,举个例子  1,2,4,6  这四个状态, 先走的将4前移,后走的将6同样也移动相同的距离,这样相当于状态没有改变,这是最优策略的影响。

2:如果存在这5个数,分不成两个两个的一组,这样就将前面的数添加一个零,得出正确的结果。 例如,存在原数据是 2,4,6,7,8 则需要在前面添加一个零,来凑成偶数,但这样做并不影响最后的结果  变成了  0,2,4,6,7,8。

3:保存两个数的差,最后得出最终的结果,将其差当成尼姆博弈时刚开始的每堆石子的个数。

post code:

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
int a[1010],b[510];
int main()
{
    
  int n,m,max,i,x,y,flag=0,result;
  scanf("%d",&n);
  while (n--)
  {
    scanf("%d",&m);
    for(i=1;i<=m;i++)
      scanf("%d",&a[i]);
    sort(a+1,a+m+1);              //对数据做一个由小到大的排序
     max=m/2;
     if(m%2==0){
                for(i=1;i<=max;i++)
                  {
                  b[i]=a[2*i]-a[2*i-1]-1;     //保存两数之差     
                  }
                 flag=1;                     //判断是偶数
                }   
     else       {
                b[1]=a[1]-1;                  //在数组前增加课一个数~~
                for(i=1;i<=max;i++)
                  {
                    b[i+1]=a[2*i+1]-a[2*i]-1;   //保存两数之差
                  }
                 flag=2;                    //判断是奇数
                } 
         result=b[1];  
     if(flag==2) 
    { 
      for(i=1;i<=max;i++)
       {  
          result=result^b[i+1];              //   对于偶数项数据进行异或操作         对于每个数据进行异或操作
       }
    }  
     else {
        for(i=2;i<=max;i++)  
            {
                   result=result^b[i];             //对于奇数项数据进行异或操作       
            }
          }   
       if(result==0)printf("Bob will win\n");            异或为零的后者胜
      else printf("Georgia will win\n");                  为一的前者省。   0为奇异局,碰到会输~~
  }

}

 

还有一道题是sg函数的练习~~

http://openoj.awaysoft.com:8080/judge/contest/view.action?cid=241#problem/A

也是类似nim博弈的变形~~

关于这道题自己想了好久:

Stone Game

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1731    Accepted Submission(s): 445


Problem Description
This game is a two-player game and is played as follows:

1. There are n boxes; each box has its size. The box can hold up to s stones if the size is s.
2. At the beginning of the game, there are some stones in these boxes.
3. The players take turns choosing a box and put a number of stones into the box. The number mustn’t be great than the square of the number of stones before the player adds the stones. For example, the player can add 1 to 9 stones if there are 3 stones in the box. Of course, the total number of stones mustn’t be great than the size of the box.
4.Who can’t add stones any more will loss the game.

Give an Initial state of the game. You are supposed to find whether the first player will win the game if both of the players make the best strategy.
 

 

Input
The input file contains several test cases.
Each test case begins with an integer N, 0 < N ≤ 50, the number of the boxes.
In the next N line there are two integer si, ci (0 ≤ ci ≤ si ≤ 1,000,000) on each line, as the size of the box is si and there are ci stones in the box.
N = 0 indicates the end of input and should not be processed.
 

 

Output
For each test case, output the number of the case on the first line, then output “Yes” (without quotes) on the next line if the first player can win the game, otherwise output “No”.
 

 

Sample Input
3
2 0
3 3
6 2
2
6 3
6 3
0
Sample Output
Case 1: Yes
Case 2: No
 
算法解析见代码:
post code:
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
  int a[10],i,c,s,sum,j,flag,result,num,capacity, ans,n,ji=0;
  a[0]=0;
  while(scanf("%d",&n)&&n!=0)
  { 
     ji++;
     sum=0;
     for(i=1;i<=n;i++)
     {
       scanf("%d %d",&c,&s);
       {
        capacity=c; 
          if(c<=s+s*s){flag=0;  ans=c-s; }      // 如果满足c<s+s*s 则此博弈为尼姆博弈
           else {   num=1;                      // 否则 此博弈为受限制的尼姆博弈
                   flag=1;
                   while(flag)
                   {  
                      result=(int)( sqrt(  float(c) )   );      
                      
                      for(j=result;j>=1;j--)
                      {
                          if(  (j+j*j<c) &&  (j*j+3*j+2>=c) )      //利用c+c*c<s and c+1+(c+1)*(c+1)>=s 计算出 必败态 @
                           {
                             a[num]=j;
                             num++;
                             break;
                           }         
                      } 
                       
                      if(j==0){
                               flag=0; 
                               a[num]=capacity;    // 将所有的必败态排序  如果容量为100的盒子,则用@给出的公式算出必败态为 100,9,2,0 
                               sort(a,a+num);
                              }
                        c=j;       
                   }
                   for(j=0;j<=num-1;j++)        
                   {
                     if(s==a[j]){ans=0;break;}     //寻找nim 博弈中每堆石子的个数: 盒子原有的石子数,距离必败态最近的值的差值
                    if(s>a[j]&&s<=a[j+1]){ans=a[j+1]-s;break;}  //例如:100 1   1距离最近的必败态为2;                   
                   }                                            // 例如 100 5   5距离最近的必败态为9;
          }
        }         
        sum=(sum^ans);                   类似与nim 博弈 对所有的每堆石子数进行异或运算 得出正确结果。
     }
     printf("Case %d:\n",ji);
     if(sum==0)printf("No\n");      
      else printf("Yes\n");            
  }    
}

 

posted @ 2012-07-08 21:18  大嘴鸟  阅读(186)  评论(0编辑  收藏  举报
Mastermate官网 香港|英国|新加坡|澳大利亚|澳门|深圳硕士研究生申请平台