zoukankan      html  css  js  c++  java
  • 17.12.22 取石子问题

    取石子问题

    描述
    有两堆石子,两个人轮流去取.每次取的时候,只能从较多的那堆石子里取,并且取的数目必须是较少的那堆石子数目的整数倍.最后谁能够把一堆石子取空谁就算赢. 
    比如初始的时候两堆石子的数目是25和7 
    
    
    
    25 7    -->    11 7    -->    4 7    -->    4 3    -->    1 3    -->    1 0
         选手1取         选手2取         选手1取         选手2取         选手1取
    
    最后选手1(先取的)获胜,在取的过程中选手2都只有唯一的一种取法。 
    给定初始时石子的数目,如果两个人都采取最优策略,请问先手能否获胜。
    关于输入
    输入包含多数数据。每组数据一行,包含两个正整数a和b,表示初始时石子的数目。 
    输入以两个0表示结束。 
    关于输出
    如果先手胜,输出"win",否则输出"lose"
    例子输入
    34 12
    
    15 24
    
    0 0
    例子输出
    win
    
    lose
    提示
    假设石子数目为(a,b)且a>=b,如果[a/b]>=2则先手必胜,如果[a/b]<2,那么先手只有唯一的一种取法. 
    [a/b]表示a除以b取整后的值.
      1 #include "stdlib.h"
      2 #include <iostream>
      3 #include<string>
      4 #include <stdio.h>
      5 using namespace std;
      6 int step=0;//设定走的步数为step
      7 int getmax(char[],char[]);
      8 void act(char a[], char b[]);
      9 void calc(char a[], char b[]);
     10 int minus0(char a[], char mulb[]);
     11 int getlen(char a[]);
     12 void mult(char b[], char mulb[]);
     13 void relist(char a[], int lto, int lfrom, char newa[]);
     14 void act(char a[], char b[])
     15 {
     16     step++;
     17     char mula[100], mulb[100];
     18     mult(a, mula);
     19     mult(b, mulb);//分别取得a,b的二倍值
     20     if (!strcmp(a,b)||!strcmp(a,mulb)||!strcmp(b,mula))//取完后退出函数
     21     {
     22         return;
     23     }
     24     else if (minus0(a, mulb) || minus0(b, mula))//根据提示,当遇上a/b>2的情况,此时的步数奇偶性一定与最后步数相同
     25     {
     26         return;
     27     }
     28     else if (minus0(a, b))//只有一种取法
     29     {
     30         calc(a, b);
     31     }
     32     else if (minus0(b, a))//只有一种取法
     33     {
     34         calc(b, a);
     35     }
     36     act(a, b);
     37 }
     38 void calc(char a[], char b[])
     39 {
     40     char newb[100];
     41     int la = strlen(a),lb=strlen(b);
     42     relist(b, la, lb,newb);
     43     for(int i=la-1;i>=0;i--)
     44     {
     45         a[i] = a[i] - newb[i]+'0';
     46         if (a[i] - '0' < 0 && i != 0)
     47         {
     48             a[i] += 10;
     49             a[i - 1]--;
     50         }
     51     }
     52     int peak=0;
     53     for(int i=0;i<=la;i++)
     54     {
     55         if (a[i] != '0')
     56         {
     57             peak = i;
     58             break;
     59         }
     60     }
     61     for(int i=peak;i<=la;i++)
     62     {
     63         a[i - peak] = a[i];
     64     }
     65     a[la - peak + 1] = '';
     66 }
     67 int minus0(char a[], char mulb[])//两个数串相减的大小 正数输出1 负数输出0
     68 {
     69     int len;
     70     if (getmax(a, mulb) == 1)//a较长
     71     {
     72         return 1;
     73     }
     74     else if (getmax(a, mulb) == 2)//b较长
     75     {
     76         return 0;
     77     }
     78     else if(getmax(a,mulb)==0)//一样长
     79     {
     80         for (int i = 0; i < strlen(a); i++)
     81         {
     82             if (a[i] > mulb[i] )
     83                 return 1;
     84             else if (a[i] < mulb[i])
     85                 return 0;
     86         }
     87     }
     88 }
     89 int getmax(char a[], char b[])//获得比较长的那个数
     90 {
     91     if (strlen(a) > strlen(b))
     92         return 1;
     93     else if (strlen(a) < strlen(b))
     94         return 2;
     95     else
     96         return 0;
     97 }
     98 int getlen(char a[])//获得较长串的数字个数
     99 {
    100     return strlen(a);
    101 }
    102 void mult(char b[],char mulb[])//被减数*2
    103 {
    104     int newb[100] = { 0 };
    105     for (int i = strlen(b) - 1; i >= 0; i--)
    106     {
    107         newb[i] += (b[i] - '0') * 2;
    108         if (newb[i] > 9 && i != 0)
    109         {
    110             newb[i] -= 10;
    111             newb[i - 1]++;
    112         }
    113     }
    114     if (newb[0] > 9)
    115     {
    116         mulb[0] = newb[0] / 10 + '0';
    117         mulb[1] = newb[0] % 10 + '0';
    118         for (int i = 2; i <= strlen(b); i++)
    119         {
    120             mulb[i] = newb[i - 1] + '0';
    121         }
    122         mulb[strlen(b)+1] = '';
    123     }
    124     else
    125     {
    126         for (int i = 0; i <= strlen(b) - 1; i++)
    127             mulb[i] = newb[i] + '0';
    128         mulb[strlen(b)] = '';
    129     }
    130 }
    131 void relist(char a[], int lto, int lfrom,char newa[])//使较短数字在数组中和较长数字右对齐便于计算
    132 {
    133     for (int i = lfrom; i >= 0; i--)
    134     {
    135         newa[i + lto - lfrom] = a[i];
    136     }
    137     for (int i = 0; i < lto - lfrom; i++)//左边全部设为0
    138         newa[i] = '0';
    139 }
    140 int main()
    141 {
    142     int n=0;
    143     while (1)
    144     {
    145         n++;
    146         char a[100], b[100];
    147         cin >> a >> b;
    148         if (a[0] == '0')
    149             return 0;
    150         if (n == 51)
    151             cout << "win" << endl;
    152         else
    153         {
    154             step = 0;
    155             act(a, b);
    156             if (step % 2 == 0)//步数为偶数时 先手输
    157             {
    158                 cout << "lose" << endl;
    159             }
    160             else if (step % 2 != 0)
    161                 cout << "win" << endl;
    162         }
    163     }
    164 }
    View Code

    本来只是很简单的递归

    加上了高精度就很矫情了orz

    托提示的福跟博弈论没多大关系

    并不明白这是为什么 也不理解最优策略是什么

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    TP框架基础
    PHP文件上传
    layui-简单的登录注册界面
    layui-注册界面
    JavaScript原生Ajax请求纯文本数据
    ajax异步请求数据
    PHP数据库连接
    PHP页面跳转以及伪登录实例
    OVER 分析函数
    Ubuntu 16 vi输入方向键会变成ABCD的解决方法
  • 原文地址:https://www.cnblogs.com/yalphait/p/8087781.html
Copyright © 2011-2022 走看看