Problem analysis

 

  • Sample input:

    10                     (N = 2   N ~= 1,000,000)
    1 2 3 4 5 2 3 4 5 6    (Each    1 ≤ Li ≤ 2000) 

  • Instead of: (1) thinking in terms of a board

    Do this: (2) thinking in terms of groups of boards of a certain length

     Length       1  2  3  4  5  6  7  8  9  10  11 ....  2000
    
     # boards:    1  2  2  2  2  1  0  0  0  0   0  ....  0 

Data representation

int N;          // # boards
int C[4001];    // C[k] = # boards of length k
                // I can use indexes 1..4000 But C[2001] C[2002] ... C[4000] = 0
                // This simplifies the algorithm because I don't get 
		// "index out of bound" when I need to find the OTHER board that
		// ADD to a specific length (<= 4000 !)

Initialization:

    /* -----------------------------
       Zero out C[ ]
       ----------------------------- */
    for (i = 1; i <= 4000; i++)
        C[i] = 0;

    /* -----------------------------
       Read in and process data
       ----------------------------- */
    cin >> N;
    for (i = 1; i <= N; i++)
    {
        cin >> k;
        C[k]++;
    }

Brute force algorithm for J5

 int maxLength = 0;    // Maximum length of fence
 int numOptions = 0;   // Number of different way to make fence

 // The possible heights of the fence are: 2 (=1+1) to 4000 (=2000 +2000)
 for ( H = 2 .. 4000 )
 {
    // Find board pairs that make height H
    numBoardPairs = 0;    // numBoardPairs = # pairs of boards that
                          //                 has combined length H
    for ( L1 = 1 .. min(H-1,2000) ) // L1 = length of board1
    {  // Board 2's length = H-L1 to make heigh = H!!!
       numBoardPairs += # pairs of boards where  
                          board1.length = L1 and 
		          board2.length = H-L1   
    }

    // Process result
    if (  numBoardPairs > maxLength )
    {
       maxLength = numBoardPairs;  // Better length
       numOptions = 1;             // First solution with this lenghth
    }
    else if ( numBoardPairs == maxLength )
    {
       numOptions++;               // Another solution with this lenghth
    }
 } 

Brute force algorithm for J5   algorithm development (and debugging)

 // The possible heights of the fence are: 2 (=1+1) to 4000 (=2000 +2000)
 for ( H = 2 .. 4000 )
 {
    // Find board pairs that make height H
    numBoardPairs = 0;    // numBoardPairs = # pairs of boards that
                          //                 has combined length H
    for ( L1 = 1 .. min(H-1,2000) ) // L1 = length of board1
    {  // Board 2's length = H-L1 to make heigh = H!!!
       numBoardPairs += # pairs of boards where  
                          board1.length = L1 and 
		          board2.length = H-L1   
    }
       Note: H-L1 can exceed 2000, that's why I used C[4001] for size
    ....



 } 

Let's focus on how to find pairs of boards with combined height H...

Brute force algorithm for J5   attemp #1

 // The possible heights of the fence are: 2 (=1+1) to 4000 (=2000 +2000)
 for ( H = 2 .. 4000 )
 {
    // Find board pairs that make height H
    numBoardPairs = 0;    // numBoardPairs = # pairs of boards that
                          //                 has combined length H
    for ( L1 = 1 .. min(H-1,2000) ) // L1 = length of board1
    {  // Board 2's length = H-L1 to make heigh = H!!!
       numBoardPairs += min( C[L1], C[H-L1] );
    }


       Note: H-L1 can exceed 2000, that's why I used C[4001] for size
    ....



 } 

DEMO: CCC/2017/Progs/j5-ver1.cc   This is not correct !!!

Brute force algorithm for J5   attemp #1

Sample input:
   L 1: 1 boards
   L 2: 2 boards
   L 3: 2 boards
   L 4: 2 boards
   L 5: 2 boards
   L 6: 1 boards

Sample output:

Height = 8:
   8: 1x: 2+6   
   8: 2x: 3+5   
   8: 2x: 4+4   
   8: 2x: 5+3   
   8: 1x: 6+2   

   8: length = 8

 

We have double counted:   board1=3 + board2=5 is the same as board1=5 + board2=3

Brute force algorithm for J5   attemp #2

 // The possible heights of the fence are: 2 (=1+1) to 4000 (=2000 +2000)
 for ( H = 2 .. 4000 )
 {
    // Find board pairs that make height H
    numBoardPairs = 0;    // numBoardPairs = # pairs of boards that
                          //                 has combined length H

    /* -------------------------------------------------
       Run L1 from 1 to H/2 to avoid double counting!!!

       Reason:
          If H is even (H=6), run L1 to H/2 (3 = 6/2)
          If H is odd  (H=5), run L1 to H/2 (2 = 5/2)
       ------------------------------------------------ */
    for ( L1 = 1 .. min(H/2,2000) ) // L1 = length of board1
    {
       numBoardPairs += min( C[L1], C[H-L1] );
    }
    ....
 } 

DEMO: CCC/2017/Progs/j5-ver2.cc   This is still not correct !!!

Brute force algorithm for J5   attemp #2

Sample input:
   L 1: 1 boards
   L 2: 2 boards
   L 3: 2 boards
   L 4: 2 boards
   L 5: 2 boards
   L 6: 1 boards

Sample output:

Height = 8:
   8: 1x: 2+6
   8: 2x: 3+5
   8: 2x: 4+4        <-- L1 = 4 and L2=4 (8-4=4)

   8: length = 5



 

When both boards have same length (L1 == L2), we need to use 2 boards from the same bucket!!

Brute force algorithm for J5   final solution

 // The possible heights of the fence are: 2 (=1+1) to 4000 (=2000 +2000)
 for ( H = 2 .. 4000 )
 {
    // Find board pairs that make height H
    numBoardPairs = 0;    // numBoardPairs = # pairs of boards that
                          //                 has combined length H

    /* -------------------------------------------------
       Run L1 from 1 to H/2 to avoid double counting!!!

       Reason:
          If H is even (H=6), run L1 to H/2 (3 = 6/2)
          If H is odd  (H=5), run L1 to H/2 (2 = 5/2)
       ------------------------------------------------ */
    for ( L1 = 1 .. min(H/2,2000) ) // L1 = length of board1
    {
       if ( L1 != H-L1 )
           numBoardPairs += min( C[L1], C[H-L1] );
       else
           numBoardPairs += C[L1]/2;
    }
    ....
 } 

DEMO: CCC/2017/Progs/j5.cc