我正在尝试实施回溯算法(它应该通过一定数量的人来检查所有可能的对,每对都有一定的分数,目标是找出“最大”分数出现的次数;所以我需要检查所有可能的解决方案。)
问题是我无法理解如何使我的功能实际上“回溯”......当它找到解决方案时,它会一直回到根目录。我如何回到可以尝试不同路径的地方,让它走上那条道路而不是再次做同样的道路呢?
这是我的代码,虽然我知道我的想法可能是错的......只是我试图在很多方面考虑它而且我绝对迷失在这里。 谢谢你的帮助!
void allPairs (int x, int pref[], bool teamed[], int* max, int score, int numWorkers) {
for (int i=1; i < numWorkers; i++) {
int count = 0;
pairTwo(x, i, pref, teamed, max, score, numWorkers, &count);
}
}
int pairTwo (int x, int y, int pref[], bool teamed[], int* max, int score, int numWorkers, int* howMany) {
if (x >= numWorkers) {
arrToZero(teamed, numWorkers);
return score;
}
else if (x==y) {
if(y < numWorkers-1) {
y = findUnteamed(teamed, y+1, numWorkers);
}
else {
arrToZero(teamed, numWorkers);
return score;
}
}
int pairScore = sumPair(pref, x, y, teamed, numWorkers);
x = findUnteamed(teamed, x, numWorkers);
y = findUnteamed(teamed, 0, numWorkers);
int temp = pairTwo(x, y, pref, teamed, max, score + pairScore, numWorkers, howMany);
teamed[x] = 0; // here I tried to "erase" the last move but it's useless
teamed[y] = 0;
if (temp >= *max) {
max = &temp;
*howMany++;
printf("There are %d optimal pairings:, with a total score of: %d\n", *howMany, *max);
return *max;
}
else {
return -1;
}
}
答案 0 :(得分:0)
如果您不遵守其遵循的确切算法,则回溯会令人困惑。回溯算法中的方法的非官方名称被广泛接受,并且有助于更容易地调试代码。
标准递归回溯算法由solve(),getSuccessors(),isGoal()和isValid()组成。使用正在进行操作的一组int的示例,solve()函数如下所示:
int[] solve(int[] list) {
if ( isGoal( list ) ) {
return list;
}
int[][] successors = getSuccessors( list )
for (int[] successor : successors) {
if ( isValid( successor ) ) {
if ( sizeof( solve( successor ) ) != 0 ) {
return successor;
}
}
}
return [];
}
getSuccessors()
返回当前数组的深层副本列表,这些列表已被修改以探索新解决方案,isGoal()
会检查是否找到了解决方案,并且isValid()
检查是否有可能找到继续沿当前路径行进的目标。这三个功能特定于您要解决的问题。
或者,存在一个迭代版本的solve(),其中初始状态被放入空堆栈中,尽管您需要首先构建一个堆栈。检查维基百科页面上的迭代回溯,看看解决方法是如何工作的。