A Boring Game

1539: A Boring Game

时间限制: 1 Sec  内存限制: 128 MB
提交: 3  解决: 3
[提交][状态][讨论版][命题人:外部导入]

题目描述

Alice has nothing to do,so she decided to paly a game. Firstly, she has three heaps of stone. The number of three heaps of stone are n1, n2, n3, respectively. At each round, she can choose two piles from the three heaps of stone, and then take a stone from each of the two piles to the heap not been choosed. For example, n1=1, n2=2, n3=3. After the first round, it can become n1=0, n2=1, n3=5 or n1=0, n2=4, n3=2 or n1=3, n2=1, n3=2. The game will end if and only if two heap of stones are empty. Now, Alice wants you to calculate the minimum rounds before the end of game.

输入

There are at most 100000 cases. For each line, there are three integer n1, n2, n3(1<=ni<=10000, i=1,2,3).

输出

For each case, print the minimum rounds. If the game will not end, print "Oh, my God!".

样例输入

1 2 3
1 2 2

样例输出

Oh, my God!
2


解题思路:首先考虑暴力搜索,这时必须要开一个vis数组来标记每种情况是否搜索过,但发现题目给出n的范围是在1-10000间,三维数组占用的空间是10000*10000*10000,会超内存,所以就不能用暴力搜索来做。
换一种思路,可以找规律,设三堆石头石头的初始数量分别为A,B,C,从A,B中拿出一块石头给C的回合有x回,从A,C中拿出一块石头给B的回合有y回,从B,C中拿出一块石头给A的回合有z回,假设经历了x+y+z回合之后,有两堆石头的数量相等了,即游戏可以结束,便得到三个等式,化简后可以发现任意两堆石头的差一定是三的倍数,所以公式就找出来了。
证明过程如下图:

#include <bits/stdc++.h>
using namespace std;

int Min=999999;
bool flag=false;

bool check(int x,int y,int z)
{
    if(x==y||x==z||y==z)//如果有两堆石头数量相等直接输出
    {
        if(x==y||x==z)Min=x;
        else if(y==z)Min=y;
        return true;
    }
    int Maxn=(x>y?x:y)>z?(x>y?x:y):z;
    int Minm=(x<y?x:y)<z?(x<y?x:y):z;
    int Medi=x+y+z-Maxn-Minm;
    for(int j=0;j<=(Maxn-Minm)/3+0.5;++j)//判断是否可以结束游戏
    {
        if(Minm+3*j==Medi)
        {
            if(Medi<Min)Min=Medi;
            flag=true;
        }
        else if(Minm+3*j==Maxn)
        {
            if(Maxn<Min)Min=Maxn;
            flag=true;
        }
        else if(Medi+3*j==Maxn)
        {
            if(Maxn<Min)Min=Maxn;
            flag=true;
        }
    }
    if(flag)return true;
    else return false;
}

int main()
{
    int a,b,c;
    while(cin>>a>>b>>c)
    {
        Min=999999;
        flag=false;
        if(check(a,b,c))cout<<Min<<endl;
        else cout<<"Oh, my God!"<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wjw2018/p/9320067.html