PSET 3 Tideman CS50 lock_pairs doesn't lock correctly

后端 未结 1 1646
梦谈多话
梦谈多话 2021-01-17 04:42

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_

1条回答
  •  说谎
    说谎 (楼主)
    2021-01-17 04:46

    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 the winner in the main loop in lock_pairs). This is constant throughout the entire recursion. Remember, once again, our goal is to iterate through all the candidates loser has won against (and also have been locked) and make sure none of these are circle_start (aka the winner 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;
            }
        }
    }
    

    0 讨论(0)
提交回复
热议问题