[英]CS50 - PSET 3 - Tideman - lock_pairs() works when I test it, but fails unit testing
[英]PSET 3 Tideman CS50 lock_pairs doesn't lock correctly
我是这个网站的新手,所以我可能无法正确提出我的问题,对此我很抱歉,但我已经在 PSET 3 Tideman 上苦苦挣扎了一段时间。 目前我在 lock_pairs 上,我不知道该怎么做。 感谢您的帮助:这些是我对 check50 的提示:
:) lock_pairs locks all pairs when no cycles
:( lock_pairs skips final pair if it creates cycle
lock_pairs did not correctly lock all non-cyclical pairs
:( lock_pairs skips middle pair if it creates a cycle
lock_pairs did not correctly lock all non-cyclical pairs
void lock_pairs(void)
{
int winner;
int win_count[MAX];
int temp_win = 0;
for (int i = 0; i < pair_count; i++)
{
locked[ pairs[i].winner ][ pairs[i].loser ] = true;
win_count[ pairs[i].winner ]++;
if (win_count [ pairs[i].winner ] > temp_win )
{
winner = pairs[i].winner;
}
}
for ( int p = 0; p < pair_count; p++)
{
if (win_count[ pairs[p].winner ] == win_count[winner] && pairs[p].winner != winner )
{
for (int i = pair_count - 1; i < -1 ; i--)
{
locked[ pairs[i].winner ][ pairs[i].loser ] = false;
win_count [ pairs[i].winner ]--;
if (pairs[i].winner == winner )
{
win_count[winner]--;
for (int j = 0; j < pair_count; j++)
{
if (win_count[ pairs[j].winner ] > win_count[winner])
{
winner = pairs[j].winner;
}
if (win_count[ pairs[j].winner] == win_count[winner] && pairs[j].winner != winner)
{
break;
}
}
}
else
{
locked[ pairs[i].winner ][ pairs[i].loser ] = true;
}
}
}
}
return;
}
您可能误解了lock_pairs
背后所需的逻辑,因为您的 function 过于复杂。 这是你被要求做的——
Go 每对一一通过,必要时锁定
如何知道,如果有必要? 很简单,您确保锁定它们不会构成一个圆圈
“构成一个圆”是什么意思? 课程本身很好地解释了这一点。 更多信息就在那里
但基本上,
在上述投票的情况下,这将如何运作? 好吧,一对胜利的最大优势是爱丽丝击败鲍勃,因为有 7 个选民更喜欢爱丽丝而不是鲍勃(没有其他正面对决的获胜者被超过 7 个选民喜欢)。 所以 Alice-Bob 箭头首先被锁定在图中。 下一个最大的胜利是查理以 6-3 战胜爱丽丝,因此箭被锁定在下一个。
接下来是鲍勃以 5-4 战胜查理。 但请注意:如果我们现在要添加一个从 Bob 到 Charlie 的箭头,我们将创建一个循环,由于该图不允许循环,我们应该跳过这条边。 并且根本不将其添加到图表中,如果要考虑更多箭头,我们将查看下一个箭头,但那是最后一个箭头。 所以图是完整的。
这个分步过程如下所示,最终图表在右侧。
现在真正的交易,你如何把它放在代码中?
像这样-
// Recursive function to check if entry makes a circle bool makes_circle(int cycle_start, int loser) { if (loser == cycle_start) { // If the current loser is the cycle start // The entry makes a circle return true; } for (int i = 0; i < candidate_count; i++) { if (locked[loser][i]) { if (makes_circle(cycle_start, i)) { // Forward progress through the circle return true; } } } return false; }
本质上,要检查锁定赢家->输家是否形成了一个圆圈,您从失败者开始退回您锁定的条目,并走向该失败者赢得的所有候选人。 如果您在途中的某个地方到达获胜者,那是一个圆圈,如果我见过的话。
请注意circle_start
,以免混淆。 那只是为了记住最初的循环开始(这是lock_pairs
主循环中的winner
)。 这在整个递归过程中是恒定的。 再一次记住,我们的目标是遍历所有loser
已经战胜(并且也被锁定)的候选人,并确保这些候选人都不是circle_start
(也就是我们即将锁定的winner
)。
因此,function 就在那里完成了所有繁重的工作,您的lock_pairs
function 将非常简单-
// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs()
{
for (int i = 0; i < pair_count; i++)
{
if (!makes_circle(pairs[i].winner, pairs[i].loser))
{
// Lock the pair unless it makes a circle
locked[pairs[i].winner][pairs[i].loser] = true;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.