【问题标题】:Combinatorial game in javajava中的组合游戏
【发布时间】:2014-08-17 19:11:14
【问题描述】:

我有一个计算机科学课的作业。我已经考虑了两个多星期没有成功,所以我决定在这里尝试一下。
游戏由 4 名 CIA 特工使用 4 个相邻的电话亭组成。他们按照一定的规则一次一个地到达一组展位:

1 - 代理选择一个其相邻的两个展位未被占用的展位(这包括位于集合边缘的展位);
2 - 如果不满足上述条件,代理商选择只有一个相邻展位空置的展位;和
3 - 如果两个条件都失败,代理选择任何展位。

根据规则,4个代理商和4个展位共有8种不同的展位占用方式。示例:代理#1 占据第一个展位(左边缘一个),然后代理#2 占据第三个展位(从左到右),然后代理#3 占据第四个展位,最后代理#4 占据第二个展位。

我们被要求编写一个代码,根据这些规则计算 19 个代理占用 19 个展位的方式数。

我对这个问题的自然选择是创建一个布尔数组,其中 false 代表一个空的展位,true 代表一个占用的展位:

public class AgentGame {

    private boolean[] booths;
    private int numberOfBooths, counter;

    public AgentGame(int nb) {

        counter = 0;
        numberOfBooths = nb;
        booths = new boolean[numberOfBooths];

    }

我一直在想一种方法来实现两种方法,一种是根据规则填充摊位,另一种是计算可以占用摊位的所有不同组合。但我无法弄清楚,还没有。这里有什么想法吗?提前致谢。

【问题讨论】:

  • 尝试使用递归方法。如果你不明白,我会在一个小时内发布一些代码。

标签: java arrays boolean combinatorics


【解决方案1】:

效率有点低,但我希望有明确的解决方案。我不能保证这会输出正确的答案(因为我喜欢犯愚蠢的错误),但这应该让你知道如何解决它。

package whyNotZoidberg;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Agents {

    public static final int N = 5;  // amount of total agents / booths 

    static int position[] = new int[N]; // index = agent, value = boot
    static boolean occupied[] = new boolean[N];
    static ArrayList<Integer> answers = new ArrayList<>();

    public static void main(String[] args) {

        for (int i = 0; i < N; i++) {
            position[i] = -1;
        }

        System.out.println("Solutions: ");
        int answer = getWays(0);

        System.out.println();
        System.out.println("The answer is ");
        System.out.println(answer);
        System.out.println();
        Collections.sort(answers,new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 > o2) {
                    return 1;
                }
                if (o2 > o1) {
                    return -1;
                }
                System.out.println("Repetition between answers detected. Quiting.");
                System.exit(0);
                return 0;
            }
        });
        System.out.println("The solutions are following (the number is agent number)");
        for (int i = 0; i < answers.size(); i++) {
            System.out.println(answers.get(i));
        }
    }

    static int getWays(int agentNr) {
        if (agentNr == N-1) {

            position[N-1] = viableBootOptions().get(0);

            int number = 0;
            for (int i = 0; i < N; i++) {

                for (int j = 0; j < N; j++) {
                    if (position[j] == i) {
                        number += (int) ((j+1) * Math.pow(10, N - i - 1));
                    }
                }
            }

            answers.add(number);

            return 1;     

        }

        int result = 0;
        ArrayList<Integer> options = viableBootOptions();

        for (int i = 0; i < options.size(); i++) {
            position[agentNr] = options.get(i);
            for (int j = agentNr + 1; j < N; j++) {
                position[j] = -1;
            }
            updateOccupied();
            result += getWays (agentNr + 1);
        }

        return result;

    }

    static ArrayList<Integer> viableBootOptions() {
        int ruleSelected = 3;
        ArrayList<Integer> result = new ArrayList<>();

        if (!occupied[0] && !occupied[1]) {
            ruleSelected = 1;
            result.add(0);
        }
        if (!occupied[N-2] && !occupied[N-1]) {
            ruleSelected = 1;
            result.add(N-1);
        }
        if (!occupied[0]) {
            if (ruleSelected != 1) {
                ruleSelected = 2;
                result.add(0);
            }
        }
        if (!occupied[N-1]) {
            if (ruleSelected != 1) {
                ruleSelected = 2;
                result.add(N-1);
            }
        }

        for (int i = 1; i < N-1; i++) {
            if (!occupied[i]) {
                if (!occupied[i - 1] && !occupied[i + 1]) {
                    if (ruleSelected > 1) {
                        ruleSelected = 1;
                        result.clear();
                    }
                    result.add(i);
                    continue;
                }
                if ((!occupied[i - 1] || !occupied[i + 1]) && ruleSelected != 1) {

                    if (ruleSelected > 1) {
                        if (ruleSelected == 3) {
                            result.clear();
                        }
                        ruleSelected = 2;   
                        result.add(i);
                        continue;
                    }

                }

                if (ruleSelected == 3) {
                    result.add(i);
                }

            }
        }
        return result;

    }

    static void updateOccupied() {
        for (int i = 0; i < N; i++) {
            occupied[i] = false;
        }
        for (int i = 0; i < N; i++) {
            if (position[i] > -1) {
                occupied[position[i]] = true;
            }
        }
    }
}

编辑:程序现在还打印找到的所有答案,并在任何答案重复时终止。您可以通过更改 N 的值来更改代理的数量。

【讨论】:

  • 非常感谢!在 4 个代理和 4 个展位的情况下,您的代码返回了 8 个组合的正确值。
  • 如果我将第 1 条规则更改为 1 是否会对代码产生任何影响 - 代理选择一个其两个相邻展位未占用的展位(这包括位于集合边缘的展位,如果是这样的话);?
  • 以下是4个代理商4个展位的占用示例:[drive.google.com/file/d/0B0TQx17rlFBIVEROSnd6TXhaZGM/…
  • 你的意思是改变?我认为第一条规则已经是你刚才描述的。还有你所说的病房影响是什么意思?如果您的意思是执行速度,那么我怀疑是否真的有任何方法可以加快这种方法的执行速度。我估计计算所需的时间将在 19 左右! / 36000000000 = ~3000000 小时。
  • 我问这个是因为我手动计算了一组 5 个代理和 5 个展位的组合数量,结果是 24 个组合,但代码返回 32。不过,我不确定是否我做得对。您将如何继续测试 4、5、...、19 个展位的代码?我是这样处理的:比如一组4个展位,4个代理,每次找到19就换成4;每当我找到 18 时,我就用 3 替换它,每当我找到 17 时,我就用 2 替换它。以此类推。这对你有意义吗?
【解决方案2】:

我会制作这个快速的 uni 代码(适用于任何代码,如果你知道该怎么做)

              Int x,z=1
              Int numberofagents;
              Int numberofbooths;
              Int emptynext; //this value allows you to control how many empty booths need to be next to one in order for an agent to pic 
              Func sortagents (numberofagents,numberofbooths,emptynext) {              



      If(booth[emptybooth].numbertotherightt>=emptyadj||booth[emptybooth].numbertotheleft>=emptyadj,z+1)
       Return (agent[z].boothnumber=emptybooth);//this statement will put agents in booths with 2 empty adjacent ones first          If(booth[emptybooth].numbertotheright>=1||booth[emptybooth].numbertotheleft>=1,z+1)
             Return (agent[z].boothnumber=emptybooth);//that one will place them into booths with one empty adjacent};   
              Int randomnumber=numberofbooths/2 //I forgot   the function for rounding but round up
              Int Boothstaken;
              Int Boothstaken=0;
              Class Booth[numberofbooths]{
              Bool Occupied;
              Int  Unoccupiedonright;
             Int  Unoccupiedonleft;
             }
             Class Agent[numberofagents]{
             Int boothnumber;
             }
             Func Boothsoccupied (x=1)
             If (booth[x].y=true&&x<Numberofbooths,x+1)
             {int Boothstaken+1
             };
             Func BoothPick //Agent picks booth
             If(Boothstaken=0,z+1)
             {agent[z].boothnumber=randomnumber}
             If(Boothstaken>0)
             {Func sortagents};

我真的希望这会有所帮助 这将简单地告诉你每个人去哪里所以找到某人去哪里很简单 代理[你想要的号码].Boothnumber 将其更改为 Java 并输出它是您的工作 我会在一分钟内回来,并给你一个功能来找出左边或右边有多少个空的摊位需要吃饭,所以我会在一分钟内回来

            Hopes this helps :) Good Luck :) ??

【讨论】:

  • 我会添加 cmets :) 我其实对这个问题很感兴趣,谢谢
猜你喜欢
  • 1970-01-01
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 2014-01-21
  • 2012-01-04
  • 1970-01-01
  • 2014-01-21
相关资源
最近更新 更多