PSET 3 Tideman CS50 lock_pairs无法正确锁定

时间:2020-07-19 11:05:24

标签: c cs50

我是这个网站的新手,所以我可能无法正确提出我的问题,对此我感到抱歉,但是我已经在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;
}

1 个答案:

答案 0 :(得分:2)

您可能误解了lock_pairs背后的逻辑,因为您的功能过于复杂。这就是您要做的-

  • 一个对一个地检查每对,并在必要时将它们锁定

  • 如何知道是否有必要?很简单,您确保将其锁定不构成圆圈

  • “构成一个圆圈”是什么意思?课程本身对此作了很好的解释。更多信息right there

    但基本上,

    在以上投票的情况下,这将如何工作?好吧,两人最大的胜利余数是爱丽丝击败鲍勃,因为有7名选民更喜欢爱丽丝,而不是鲍勃(没有其他正面交锋的比赛,胜者超过7名选民)。因此,Alice-Bob箭头首先被锁定到图形中。下一个最大的胜利余地是查理以6-3击败爱丽丝,因此箭号紧随其后。

    接下来是鲍勃5-4击败查理。但是请注意:如果我们现在要添加一个从鲍勃到查理的箭头,我们将创建一个循环!由于图表不允许循环,因此我们应该跳过此边缘,而不要将其完全添加到图表中。如果要考虑的箭头更多,我们将转到下一个箭头,但这是最后一个箭头,因此图形已完成。

    此分步过程如下所示,最终图形在右侧。

  • 现在真正的交易了,如何将其放入代码中?

    像这样-

    // 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,以免引起混淆。仅在那里记住原始的圆起点(即winner主循环中的lock_pairs)。在整个递归中,此常数是恒定的。再次记住,我们的目标是遍历 loser赢得(也被锁定)的所有候选人,并确保所有候选人都不是circle_start(又名我们将要锁定的winner )。

因此,该函数完成了所有繁重的工作,您的lock_pairs函数将非常简单-

// 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;
        }
    }
}