【问题标题】:Finding optimal solution寻找最优解
【发布时间】:2013-07-30 04:48:59
【问题描述】:

我们有 7 件衬衫以随机顺序排列,例如 3 4 5 7 1 6 2。 我们可以对它们执行 4 次操作。 在每次操作中,将脱下的衬衫放入制作的间隙中。

  1. 取下中间的衬衫并将相邻的 3 件衬衫向右移动。
  2. 取下中间的衬衫,将相邻的 3 件衬衫向左移动。
  3. 移除最左边的衬衫并将相邻的 3 件衬衫移至左侧。
  4. 移除最右边的衬衫并将相邻的 3 件衬衫移至右侧。

给定 7 件衬衫以随机顺序排列,找出将衬衫按顺序排列所需的最少操作次数,即 1 2 3 4 5 6 7。

我尝试了一个使用排列的解决方案,但超过 7 次操作都失败了。

这是我的解决方案:

import java.util.*;

类衬衫2 {

public static void main(String[] ar)
{

    Scanner sc = new Scanner(System.in);
    String n = sc.next();
    if(n.equals("1234567"))
    {
        System.out.println("0");
        System.exit(0);
    }
    for(int i = 1; ; i++)
    {
        PermutationsWithRepetition gen = new PermutationsWithRepetition("1234",i);
        List<String> v = gen.getVariations();
        for(String j : v)
        {
            String t = n;
            for(int k = 0;k < j.length(); k++)
            {
                int l = j.charAt(k) - '0';
                t = operation(t,l);
            }
            if(t.equals("1234567"))
            {
                System.out.println(i + "\t" + j);
                System.exit(0);
            }
        }
     }
}

public static String operation(String t, int l)
{
    if(l == 1)
        return "" + t.charAt(3) + t.substring(0,3) + t.substring(4);
    else if(l == 2)
        return t.substring(0,3) + t.substring(4) + t.charAt(3);
    else if(l == 3)
        return t.substring(1,4) + t.charAt(0) + t.substring(4);
    else
    {
        return t.substring(0,3) + t.charAt(6) + t.substring(3,6);
    }
}

}

public class PermutationsWithRepetition {
private String a;
private int n;
public PermutationsWithRepetition(String a, int n) {
    this.a = a;
    this.n = n;
}
public List<String> getVariations() {
    int l = a.length();
    int permutations = (int) Math.pow(l, n);
    char[][] table = new char[permutations][n];

    for (int x = 0; x < n; x++) {
        int t2 = (int) Math.pow(l, x);
        for (int p1 = 0; p1 < permutations;) {
            for (int al = 0; al < l; al++) {
                for (int p2 = 0; p2 < t2; p2++) {
                    table[p1][x] = a.charAt(al);
                    p1++;
                }
            }
        }
    }


    List<String> result = new ArrayList<String>();
    for (char[] permutation : table) {
        result.add(new String(permutation));
    }
    return result;
}
public static void main(String[] args) {

    PermutationsWithRepetition gen = new PermutationsWithRepetition("abc", 3);
    List<String> v = gen.getVariations();
    for (String s : v) {
        System.out.println(s);
    }
}

【问题讨论】:

  • 你尝试过什么递归解决方案?它的失败有多严重?请更新您的问题并提供更多详细信息。
  • 发布您迄今为止尝试过的代码将使我们能够更好地帮助您,也将展示您的努力!!
  • 如果你打算用蛮力来做,只需用四路节点制作一棵树,其中每路代表一种方法。如果您在其中一个节点上遇到答案,请将其打印出来。如果您跟踪迭代,您就知道它执行了多少步,如果您跟踪路径,您就知道它使用了哪些操作。
  • @bas 你甚至可以为此使用 fork-join。

标签: java algorithm brute-force


【解决方案1】:

如果您打算以蛮力进行,只需制作一棵具有四路节点的树,其中每路代表一种方法。如果您在其中一个节点上遇到答案,请将其打印出来。如果您跟踪迭代,您就知道它执行了多少步,如果您跟踪路径,您就知道它使用了哪些操作。

public static void main(String[] args)
{
    int[] shirts = new int[] { 3, 4, 5, 7, 1, 6, 2 };

    Path shortestPath = shirtAlgorithm(shirts);
}


public static class Path
{
    private ArrayList<Integer> path;
    private int[] shirts;

    public Path(ArrayList<Integer> _path_, int[] _shirts_)
    {
        this.path = _path_;
        this.shirts = _shirts_;
    }

    public void setPath(ArrayList<Integer> _path_)
    { this.path = _path_; }

    public ArrayList<Integer> getPath()
    { return this.path; }

    public void setShirts(int[] _shirts_)
    { this.shirts = _shirts_; }

    public int[] getShirts()
    { return this.shirts; }
}




public static Path shirtAlgorithm(int[] shirts)
{
    ArrayList<Path> paths = new ArrayList<>();

    paths.add(new Path(new ArrayList<Integer>(), shirts));

    while (true)
    {
        ArrayList<Path> newpaths = new ArrayList<Path>();

        for (Path curpath : paths)
        {
            for (int operation = 1; operation <= 4; operation++)
            {
                ArrayList<Integer> curnewpath = new ArrayList<Integer>(curpath.getPath());
                curnewpath.add(operation);

                Path newestPath = new Path(
                        curnewpath, 
                        operation(curpath.shirts, operation));

                if (algorithmComplete(newestPath))
                    return newestPath;

                newpaths.add(newestPath);
            }
        }

        paths = newpaths;
    }
}

private static int[] operation(int[] shirts, int operationtype)
{
    int[] newshirts = new int[shirts.length];
    System.arraycopy(shirts, 0, newshirts, 0, shirts.length);
    // logic here
    return newshirts;
}

private static boolean algorithmComplete(Path path)
{
    // true if the shirts are in the right order
}

这是您操作中最简单的蛮力算法之一。

【讨论】:

  • 第一个路径是从哪里来的。
  • 我认为树是最好的方法之一。如果你想让它更有效,你将不得不制作一个广度优先树而不是深度优先树。这意味着不是一直迭代到路径的深度,而是同时迭代所有路径。这样,一旦路径找到一条路,您就可以停止整个算法。
  • 关于广度优先树的一些信息:stackoverflow.com/questions/1657174/…
  • 我将如何检查答案。并且您没有为递归函数包含任何基本条件。
  • 你自己填,我可以给个简单的骨架模型
【解决方案2】:

尝试 A* 寻路方法,这是一种最好的方法 这是算法:

  1. 开始。
  2. 找到目标状态的近似成本估算(这是每件衬衫从其在目标状态的位置的总位移......这意味着如果衬衫 1 在位置 3,它的位移是 2,如果衬衫3 位于位置 1,其位移为 2(仅幅度 )。将它们全部加起来以获得达到目标的成本估算。对于您给出的起始状态,成本估算为 18)
  3. 对于这个状态,计算它的每个相邻状态的成本估计。(在这个问题中,有四个可能的等距相邻状态(移动 1 导致新状态,移动 2 导致不同状态和依此类推),因此评估成本估计以达到所有这些相邻状态的目标状态。
  4. 选择在每个州达到目标的估计成本最低的州。 在每个州,确保相邻州的成本估计低于当前状态的成本估计。
  5. 您最终将进入目标状态(达到目标的成本估计为 0)

希望这会有所帮助。 :)

【讨论】:

  • 但经过一些操作后,它开始重复。在我给出的示例中,它到达 1345627,然后到达 5134627,然后又到达 1345627。
  • 您需要对目标状态使用有效检查。一般的想法是使用估计函数来评估状态与目标状态的距离。 (在这种情况下,您可以使用总位移功能)。该函数在目标状态下为 0。所以检查一下 while(!H(state)==0) { 做操作 }
猜你喜欢
  • 1970-01-01
  • 2019-04-09
  • 2023-03-24
  • 2018-11-28
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多