zoukankan      html  css  js  c++  java
  • HDU 1525

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1525

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

    Problem Description
    Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7):
    25 7
    11 7
    4 7
    4 3
    1 3
    1 0
    an Stan wins.

    Input
    The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.
     
    Output
    For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.

    Sample Input
    34 12
    15 24
    0 0
     
    Sample Output
    Stan wins
    Ollie wins
     
    作为一道博弈题,我这种只会套模板不会动脑筋的咸鱼只好完全听从网上题解的话,老老实实找规律……
     
    题意:
    有2个数,2个人轮流把大的数(设为a)减去小的数(设为b)的倍数(不能超过大的数),一直到有一方能把某个数减到0,该方获胜。Stans先走,问最后赢的是谁。
     
    题解:
    首先我们把这对数按(a,b)(始终假设使得a>b,这个对于实际操作时没有影响,只是方便操作)表示;
      情况①:(a,b)满足b == 0,这个时候是必败局。
      情况②:(a,b)满足a%b == 0,这个时候,便是必胜局。
      情况③:(a,b)满足a/b >= 2(但a%b != 0),那么当前操作者肯定可以把(a,b)变成(a%b,b)或者(a%b+b,b),而因为对于任意一个(a,b)要么是必胜局,要么是必败局;
          故在参赛者是最聪明最有预见性的前提下,那么他必然可以得知(a%b,b)是必胜局还是必败局;
          若(a%b,b)是必胜局,直接做(a,b)→(a%b+b,b)操作,那么对手必然只能做(a%b+b,b)→(a%b,b)操作,这样就可以使得我们得到必胜局情形。
          若(a%b,b)是必败局,那么直接做(a,b)→(a%b,b)操作,使得对手面对必败局情形,这样我们依然是必胜。
          故综合以上情况,情况③是必胜局情形。
      情况④:(a,b)满足b<a<2*b,这种情况,我们只有一种选择,就是做(a,b)→(a-b,b)操作,这时只能老老实实继续操作下去,直到遇到必败局或者必胜局为止。
     
    这样,我们便把游戏所有的情况都列举了出来,具体考虑怎么写成代码,也可以参考上面的情况写:
    ①首先保证a>b(通过if+swap);
    ②设定一个布尔类型的winner变量,winner==1代表Stan(先手)赢,winner==0代表Ollie(后手)赢;
    ③做一个while(1)的循环
      ④判断b==0?,若为真,当前操作者面对必败局,故winner=!winner,然后break;
      ⑤判断a%b==0 或者a/b >= 2 ?,若为真,则当前操作者面对了必胜局,直接break;
      ⑥剩下的情况只可能是上前列举的“情况④”,这时老老实实a-=b,swap(a,b),winner!=winner,代表当前操作者别无选择,只能按规则操作,并且下一步操作者变成对方。
    ⑦输出谁是胜者。
     
    AC代码:
     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int a,b;
     5 bool winner;
     6 int main()
     7 {
     8     while(scanf("%d%d",&a,&b) && a!=0 && b!=0)
     9     {
    10         if(a<b) swap(a,b);
    11         winner=1;
    12         while(1)
    13         {
    14             if(b==0)
    15             {
    16                 winner=!winner;
    17                 break;
    18             }
    19             if(a%b==0 || a/b>=2) break;
    20             a-=b;
    21             swap(a,b);
    22             winner=!winner;
    23         }
    24         printf("%s wins
    ",winner?"Stan":"Ollie");
    25     }
    26 }
  • 相关阅读:
    JavaScript Date对象和函数 (一)
    Css3 文字渐变整理(一)
    Asp.net Core CacheHelper 通用缓存帮助类
    .net core中使用GB2312编码的问题
    苹果手机微信浏览器select标签选择完成之后页面不会自动回到原位
    .Net Core NOPI操作word(二) 表格操作
    .Net Core NOPI操作word(一)
    .NetCore中EFCore的使用整理(三)-关联表操作
    windos server2012安装.net core 2.2问题
    C# 最简单的使程序单进程运行的方法
  • 原文地址:https://www.cnblogs.com/dilthey/p/7512023.html
Copyright © 2011-2022 走看看