【问题标题】:algorithm that does not turn back and selects only one solution [duplicate]不回头且仅选择一种解决方案的算法[重复]
【发布时间】:2013-10-17 14:43:27
【问题描述】:

例如,有一个 4x4 整数数组,我需要从每一行中选择一个数字,以便每个选定的数字位于不同的列中,并且所选数字的总和尽可能低。有问题的网格如下所示:

 1 2 3 1
 2 3 1 3
 2 2 1 2
 3 4 1 9 

我的程序返回这个答案:

1* 2 3 1
2 3* 1 3
2 2 1* 2
3 4 1  9*

但最好的解决方案是:

 1 2 3 1*
 2 3 1* 3
 2* 2 1 2
 3 1* 1 9

我需要对我的功能进行哪些更改?

 struct r{
    bool moze;
    int quantity;
};
int ff,m1;
bool check(int n,r **tab, int k)
{
    for(int i=0;i<n;i++){
        if(tab[k][i].moze==true || tab[i][ff].moze==true)
            return false;
    }
    return true;
}

bool back(int n, r ** tab, int k){
    for(int i=0;i<n;i++){
        if (check(n,tab,k)){
            tab[k][i].moze=true;
            if (k==n-1)
            {
                for(int j=0;j<n;j++)
                {
                    for(int c=0;c<n;c++)
                    {
                        if(tab[j][k].moze==true)
                            cout<<tab[j][i].quantity;
                    }
                }
                return true;
            }

            if (back(n,tab,k+1))
                return true;
            else

                tab[k][i].moze=false;
        }
    }
    return false;
}

如何修复我的功能??


function mark(r, c, available):
    for each element in [r][]:
        mark available
    for each element in [][c]:
        mark available

function backtrack(table, temp, r, c, sum):
    check if sum is solution
    for row i in table:
        if temp[i][0] is not available go to next row
        for column j in table:
            if temp[i][j] is available:
                 mark(i, j, not available) 
                 backtrack(table, temp, i, j, sum+table[i][j])
                 mark(i, j, available again)

我有一个伪代码,但我不能把它放在我的函数中,有人可以帮助我吗,不能帮助自己

【问题讨论】:

  • 你要做的是:首先考虑算法,然后实现它。不是相反。
  • 为什么这个问题会被连续发布?这是我在过去三天里第五次看到它。
  • @Kunal 一定是某处的功课...
  • 那么,这是什么,你已经第六次问这个问题了(我想你也问过其他人)?这样做不太可能让你得到答案。一方面,许多用户看到了所有/大部分这些问题,并因此立即对您产生负面影响。但主要原因是,如果你不改变太多,反应就不太可能改变。而是调查提出问题缺乏结果背后的原因。如果您删除您的问题,如果有人打算提供帮助,他们将无法这样做,因为它不再存在。
  • 我看不出这个问题是怎么回事......除非你想复杂化。您可以做的一件事是将这个问题视为一个排列问题,使用std::next_permutation,并且对于每个排列,检查乘法。不要忘记用最佳解决方案保持排列。

标签: c++ algorithm stl-algorithm


【解决方案1】:

由于这只是一个小数组,您可以暴力破解(有 4!=24 种可能性)并选择最好的一个

此函数为您提供最小总和,如果您还需要选定的元素,很容易调整代码。 请注意,假设 INF 很大,而 M 是您给定的 4x4 数组。

int aux(){
  std::vector<int> t(4);
  for(int i=0;i<4;++i)
    t[i]=i;
  int mini=INF;

  do{
    int tmp=0;
    for(int i=0;i<4;++i)
      tmp+=M[i][t[i]];
    mini=std::min(mini, tmp);
  }while(std::next_permutation(t.begin(), t.end()));

  return mini;
}

【讨论】:

  • bruteforce 我做,数组 4x4 这只是一个例子,我正在寻找回溯一个大小为 N 的数组的解决方案
  • 问题并不清楚。无论如何,这是一个最小成本的二分匹配问题,您可以使用在 O(n^3) 中运行的Hungarian algorithmHere 是一个很好的参考,一个简单但 O(n^4) 的算法和更好的 O(n^3) 算法。
  • 我知道它可以解决其他算法,但是我必须解决bactracking,我的回溯,只选择一个解决方案,不回去,不寻找更好的解决方案,我不知道要改变什么做到这一点
  • 您的函数似乎在 O(n^2) 中运行,解决了一般情况,与匈牙利的算法相比非常简单。所以很可能,它是错误的,你无法修复它。
【解决方案2】:

目前您的函数只返回它找到的第一个结果。

你需要,而不是你的 2 个return 语句,只记录你去的最佳结果。

我不会为你编写代码,因为你会通过自己弄清楚它来了解更多信息,但这里有 2 条提示可以帮助你开始:

  • 您可能希望将最佳结果存储在函数之外,而不是四处传递。
  • 要存储最佳结果,您必须存储所有所选值的索引,而不仅仅是结果总和。

希望对你有所帮助。

【讨论】:

  • 这有帮助,但我还是不明白
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2012-02-15
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 2018-10-06
  • 1970-01-01
相关资源
最近更新 更多