【问题标题】:How to solve this program better如何更好地解决这个程序
【发布时间】:2014-07-27 17:03:16
【问题描述】:

以下问题来自最近的一次编程竞赛。

GCD 游戏

生与死,输赢 - 双方都有对方。这就是 Arjit 和 Chandu Don 争论的焦点。他们厌倦了彼此之间的帮派战争,因此决定像男人一样定居在数学领域。
但即使是去玩数学游戏,他们也没有放弃互相伤害的战术。所以,Arjit 随身携带了数颗橡皮子弹,Chandu Don 携带了 b 颗橡皮子弹。既然小昌杜是两人中比较危险的黑帮,他决定把第一次机会给阿吉特。
他们决定谁赢得整个 HEpur 土地的方式是玩古老的 GCD-DCG 游戏。第一个最终只有 1 颗子弹的子弹将会失败。 游戏是这样进行的:

1. If GCD (a, b) is greater than 1, then, the player can: 
    a.) Subtract 1 from opposite player’s bullets. **OR** 
    b.) Divide the number of bullets of opposite player by GCD (a, b). 
2. If GCD (a, b) is equal to 1, then, the player can: 
    a.) Subtract 1 from the opposite player’s bullets.

Note : Player can choose only one move out of two if GCD(A,B) > 1 .

The one who ends up with only one bullet loses the battle, 
and his life, and the land of HEpur.

一劳永逸地决定谁来统治!

输入:
第一行包含测试用例的数量 T,接下来的 T 行包含 Arjit 和 Chandu Don 分别取的两个数字 A 和 B。

输出:
在抽签的情况下打印比赛获胜者的姓名。 约束

1 <= T <= 1000
1 <= A <= 1000
1 <= B <= 1000

问题陈述来源:Arjit Srivastava。

Sample Input
4
2 1
3 4
5 5
1 1
Sample Output
Arjit
Chandu Don
Arjit
Draw

我在这里添加我的解决方案:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class TestClass 
{
    public static void main(String args[] ) throws Exception 
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int noOfTestCases = Integer.parseInt( br.readLine() );

        for( int inx = 0; inx < noOfTestCases; ++inx )
        {
            StringTokenizer st = new StringTokenizer( br.readLine() );

            int a = 0;
            int b = 0;

            while( st.hasMoreTokens())
            {
                a = Integer.parseInt( st.nextToken() );
                b = Integer.parseInt( st.nextToken() );                     
            }

            doStuff( a, b, true);
        }
    }

    private static boolean doStuff(int a, int b, boolean arjitInPlay ) 
    {
        if( a == 1 && b == 1 )
        {
            System.out.println( "Draw" );
            return true;
        }

        if( a == 1 )
        {
            System.out.println( "Chandu Don" );
            return true;
        }

        if( b == 1 )
        {
            System.out.println( "Arjit" );
            return true;
        }

        int result = getGCD( a, b );


        if( arjitInPlay )
        {
            if( result > 1 )
            {
                return doStuff( a, b - 1, !arjitInPlay ) || doStuff( a, b / result, !arjitInPlay );
            }
            else if ( result == 1 )
            {
                return doStuff( a, b - 1, !arjitInPlay );
            }
        }
        else
        {
            if( result > 1 )
            {
                return doStuff( a - 1, b, !arjitInPlay ) || doStuff( a / result, b, !arjitInPlay );
            }
            else if ( result == 1 )
            {
                return doStuff( a - 1, b, !arjitInPlay );
            }               
        }
        return false;
    }

    private static int getGCD(int a, int b) 
    {
        if (b == 0)
        {
            return a;
        }
        return getGCD(b, a % b);
    }
}

我有两个问题:

  • 递归是可以在这里使用的最佳数据结构吗?还是这需要另一个数据结构或算法类。
  • 有一个概念叫做正确修剪。在确定它们不会产生好的结果后,很少有路径被切断。有人可以帮我如何修剪上面的代码[比短路更好]。
  • 此代码可能有什么问题? 3 个测试中有 1 个通过。其他两个都失败了。

谢谢, 帕万。

【问题讨论】:

  • 如果您提供了失败的测试,而不是让我们都猜测,这将很有帮助。
  • @DavidWallace 恐怕这是不可能的。问题是它们是未公开的竞赛测试用例。
  • 所以你基本上是在要求 SO 社区为你测试你的代码,并告诉你错误是什么?我认为没有人真的有时间这样做,但我可能错了。如果你能具体说明失败的具体原因,那么几乎肯定会有人告诉你原因。但以目前的形式,我认为你根本不会得到任何问题的答案。

标签: java algorithm recursion dynamic-programming


【解决方案1】:

我还没有尝试在任何自动裁判系统上解决问题,但我有以下建议:

假设他们玩得最好。

根据约束使用递归是完全可以的,但是你的实现有一个错误。您的代码所做的只是每转一圈,每个用户从对面移除 1 个子弹,我认为您的短路中的第二个函数调用都没有执行。换句话说,您的代码将宣布拥有更多子弹的人为获胜者。您可以尝试8 5 作为输入。您的代码输出“Arjit”,但实际上应该是“Chandu Don”。

恕我直言,解决问题的最佳方法是使用 3D 数组 win[i][j][k],而不是使用类似 DFS 的到达 1 并完成计算方法,表示玩家 k 是否会在何时获胜当玩家 0 有 i 子弹而玩家 1 有 j 子弹时,他应该做出动作。请注意,只有在输入为1 1 时才能进行抽奖游戏。

以玩家 0 为例,当且仅当 win[i][j - 1][1]Falsewin[i][j / gcd(i, j)][1](如果 gcd(i, j) &gt; 1)是 False 时,win[i][j][0]True。玩家 1 的计算也是类似的。

我知道这与您的想法基本相同,但这样做可以为所有a b 缓存计算结果,因此未来的查询/访问将非常快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多