问题
i am new to this site so i might not ask my question correctly which i am sorry for but i have been struggling with PSET 3 Tideman for quite a while. Currently i am on lock_pairs and i dont know what to do. Would appreciate your help! These are my prompts for 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:
You may have misunderstood the logic required behind lock_pairs
, because your function is overly complicated. This is what you're asked to do-
Go through each pair one by one, and lock them if necessary
How to know, if it is necessary? Simple, you make sure locking them does not constitute a circle
What does "constitute a circle" mean? This is explained very well by the course itself. More info right there
But basically,
How would this work in the case of the votes above? Well, the biggest margin of victory for a pair is Alice beating Bob, since 7 voters prefer Alice over Bob (no other head-to-head matchup has a winner preferred by more than 7 voters). So the Alice-Bob arrow is locked into the graph first. The next biggest margin of victory is Charlie’s 6-3 victory over Alice, so that arrow is locked in next.
Next up is Bob’s 5-4 victory over Charlie. But notice: if we were to add an arrow from Bob to Charlie now, we would create a cycle! Since the graph can’t allow cycles, we should skip this edge, and not add it to the graph at all. If there were more arrows to consider, we would look to those next, but that was the last arrow, so the graph is complete.
This step-by-step process is shown below, with the final graph at right.
Now the real deal, how do you put this in code?
Like this-
// 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; }
Essentially, to check if locking in a winner->loser makes a circle, you walk back the entries you have locked starting from the loser and going towards all the candidates this loser has won against. If you reach the winner somewhere along the way, that's a circle if I've ever seen one.
Note that
circle_start
though, lest it gets confusing. That's only there to remember the original circle start (which is thewinner
in the main loop inlock_pairs
). This is constant throughout the entire recursion. Remember, once again, our goal is to iterate through all the candidatesloser
has won against (and also have been locked) and make sure none of these arecircle_start
(aka thewinner
that we are about to lock in).
So, that function right there does all the heavy lifting, your lock_pairs
function is gonna be extremely simple-
// 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;
}
}
}
来源:https://stackoverflow.com/questions/62979416/pset-3-tideman-cs50-lock-pairs-doesnt-lock-correctly