C编程题(31)

[题目] 

甲乙两人从24枚棋子中轮流取子,甲先取,规定每次所取的枚数不能多于上一个人所取的枚数,也不可不取。
  (1)甲第一次取多少枚才能保证甲取得最后一枚,当然,他也不能第一次就把所有棋子都取走。
  (2)讨论棋子总数N(一定是偶数)从6到30的各种情况。讨论内容包括:
 对各个N,是否存在一个小于N的枚数M,甲第一次取M枚后就能保证甲如果策略正确,一定能取到最后一枚棋子。

[C#]

 



        
public   const   int  N  =   24 ;
        
public   static   int [] L  =   new   int [N + 1 ];

        
public   static   void  Main(String[] args)
        {
            
for  ( int  i  =  N  -   1 ; i  >   0 ; i -- )
            {
                Console.WriteLine(
" First Time get: {0} " , i);
                L[
0 =  i;
                Solve(
1 , N - i , i);
                Console.WriteLine();
            }
            Console.ReadLine();            
        }

        
public   static   void  Solve( int  count,  int  leave, int  num)
        {
            
int  i,j;
            
if  (leave  ==   1    &&  count  %   2   ==   0   &&  count  >   1 )
            {
                L[count] 
=   1 ;
                
for  (i  =   0 ; i  <=  count; i ++ )
                    Console.Write(
" {0,4} " , L[i]);
                Console.Write(
" " );
                
return ;
            }

            
if  (leave  <   0 )
                
return ;

            
// 每次所取的枚数不能多于(也就是<=)上一个人所取的枚数
            
// 如果是:每次所取的枚数不能大于等于上一个人所取的枚数
            
// 则应该改为:for (j = num - 1; j > 1; j--) 
             for  (j  =  num; j  >   0 ; j -- )
            
// for (j = num - 1; j > 1; j--)                             
            {
                L[count] 
=  j;
                Solve(count 
+   1 , leave - j , j);
            }
        }

 

[C++]

 

/*
甲只要保证第一次取完后留给乙的棋子数是的n次方,且大于所取走的棋子数就必胜
因此,如果开始的棋子数是的n次方,则甲无必胜方法
下面的程序演示了甲的策略,(程序包含了出错处理,所以比较长)
*/

#include 
< stdlib.h >
#include 
< iostream >
using   namespace  std;

#define  MAX 100000

int  num( int  n, int  k = 0 );

int  main()
{
    
int n,k,m;
    cout
<<"请输入不大于"<<MAX<<"的正整数,输入退出"<<endl;
    
while(cin>>n&&(n>MAX||n<0))
        cout
<<"请重新输入"<<endl;
    
if(n==0)
        
goto END;
    m
=num(n);
    
if(m<0)
        
goto END;
    n
-=m;
    
while(n!=0)
    
{
        cout
<<"我取走"<<m<<" 剩余:"<<n<<endl<<"请问你取走多少个?"<<endl;
        
while(cin>>k&&(k>m||k<0||k>n))
            cout
<<"请重新输入"<<endl;
        
if(k==0)
            
goto END;
        n
-=k;
        cout
<<"你取走"<<k<<" 剩余:"<<n<<endl;
        
if(n==0)
        
{
            cout
<<"你胜利了!"<<endl;
            
goto END;
        }

        m
=num(n,k);
        
if(m<0)
            
goto END;
        n
-=m;
    }

    cout
<<"我取走"<<m<<" 剩余:"<<n<<endl;
    cout
<<"你输了"<<endl;
END:system(
"pause");
    
return 0;
}


int  num( int  n, int  k)
{
    
if(n<=k)
        
return n;
    
int i,t=1;
    
while(t<=n)
    
{
        t
*=2;
    }

    t
/=2;
    
if(t==n)
    
{
        
if(k==0)
            cout
<<"非必胜"<<endl;
        t
=n/2+2;
    }

    
else if(k==0)
        cout
<<"必胜"<<endl;
    t
=n-t;
    
if(t>k&&k!=0)
    
{
        t
=1;
        
while(t<=k&&n%t==0)
            t
*=2;
        t
/=2;
    }

    
if(t<1||(k!=0&&t>k)||t>n)
    
{
        cout
<<"Error:"<<endl<<n<<" "<<k<<" "<<t<<endl;
        
return -1;
    }

    
return t;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值