zoukankan      html  css  js  c++  java
  • hdu 2177(威佐夫博奕+打表)

    取(2堆)石子游戏

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2622    Accepted Submission(s): 1594

    Problem Description
    有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。如果你胜,你第1次怎样取子?
    Input
    输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,且a<=b。a=b=0退出。
    Output
    输出也有若干行,如果最后你是败者,则为0,反之,输出1,并输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。如果在任意的一堆中取走石子能胜同时在两堆中同时取走相同数量的石子也能胜,先输出取走相同数量的石子的情况.
    Sample Input
    1 2
    5 8
    4 7
    2 2
    0 0
    Sample Output
    0 1
    4 7
    3 5
    0 1
    0 0
    1 2
    Author
    Zhousc
    Source
    [x y]可以转换三种状态(1)[x-k,y] (2)[x,y-k] (3)[x-k,y-k]
    只要这三种里面出现至少一种输的状态 [x,y]就是必胜态  否则[x,y]必败
    所以我们可以打表发现规律
    打表代码
     1 const int N=100;
     2 int a[N][N];
     3 int main(){
     4     int i,j,k;
     5     a[0][0]=0;
     6     for(i=1;i<N;i++){
     7         a[0][i]=a[i][0]=1;
     8     }
     9     for(i=1;i<N;i++){
    10         for(j=1;j<N;j++){
    11             a[i][j]=0;
    12             for(k=0;k<i;k++)
    13             if(a[k][j]==0)a[i][j]=1;
    14             for(k=0;k<j;k++)
    15             if(a[i][k]==0)a[i][j]=1;
    16             for(k=1;k<=min(i,j);k++)
    17             if(a[i-k][j-k]==0)a[i][j]=1;
    18         }
    19     }
    20     for(i=0;i<20;i++){
    21         for(j=0;j<20;j++)
    22         printf("%d ",a[i][j]);
    23         printf("
    ");
    24     }
    25 }

    输出前20组数据

    我们可以发现这几种情况是输的

    1 2

    3 5

    4 7

    6 10 可以发现规律为 a=(int)(b-a)(aqrt(5)+1)/2 我也不知道规律怎么得到这个公式的

    输出为1的情况 我们只需要让状态转为必败的状态就可以了

    int t=(b-a)*(sqrt(5)+1)/2;

    if(t<a)  假设 bb=b-(a-t)  及证明 t 和bb满足必败的条件、、

    (bb+t-a-t)*(sqrt(5)+1)/2=(b-a)*(sqrt(5)+1)/2=t;

    并且这种情况属于[x-k,y-k]这种  所以我们可以先判断

    其他的两种自己看代码想  不想解释了

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cctype>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<map>
     8 #include<stack>
     9 #include<set>
    10 #include<vector>
    11 #include<algorithm>
    12 #include<string.h>
    13 typedef long long ll;
    14 typedef unsigned long long LL;
    15 using namespace std;
    16 const int INF=0x3f3f3f3f;
    17 const double eps=0.0000000001;
    18 const int N=500000+10;
    19 const int MAX=1000+10;
    20 int main(){
    21     int n,m;
    22     while(scanf("%d%d",&n,&m)!=EOF){
    23         if(n==0&&m==0)break;
    24         double b=(sqrt(5.0)+1)/2;
    25         if(n==(int)(b*(m-n))){
    26             cout<<0<<endl;
    27             continue;
    28         }
    29         cout<<1<<endl;
    30         int t=(int)(m-n)*b;
    31         if(t<n)cout<<t<<" "<<t+m-n<<endl;
    32         for(int i=0;i<=m;i++){
    33             int x=m-i;
    34             if(x>n&&(int)(b*(x-n))==x)cout<<x<<" "<<n<<endl;
    35             else if(x<n&&(int)(b*(n-x))==x){
    36                 cout<<x<<" "<<n<<endl;
    37             }
    38         }
    39     }
    40 }
     
  • 相关阅读:
    英文网站优化之十个非常不错的Zen Cart插件
    kindeditor4.0.4个性化修改
    C#线程从陌生到熟悉(1)
    c# 关于LISTBOX的添加项的问题 以及不重复插入
    CSS设置字体为楷体
    SqlServer2005安装成功后补加Sa用户
    c# winform 用子窗体刷新父窗体,子窗体改变父窗体控件的值
    实例讲解如何把表格变量传递到存储过程中
    StringBuilder
    初学基于.net三层架构的ERP系统(1)
  • 原文地址:https://www.cnblogs.com/Aa1039510121/p/6914766.html
Copyright © 2011-2022 走看看