Bomb dropping algorithm

后端 未结 30 842
挽巷
挽巷 2021-01-29 16:55

I have an n x m matrix consisting of non-negative integers. For example:

2 3 4 7 1
1 5 2 6 2
4 3 4 2 1
2 1 2 4 1
3 1 3 4 1
2 1 4 3 2
6 9 1 6 4
         


        
30条回答
  •  -上瘾入骨i
    2021-01-29 17:37

    Mathematica Integer Linear Programming using branch-and-bound

    As it has already been mentioned, this problem can be solved using integer linear programming (which is NP-Hard). Mathematica already has ILP built in. "To solve an integer linear programming problem Mathematica first solves the equational constraints, reducing the problem to one containing inequality constraints only. Then it uses lattice reduction techniques to put the inequality system in a simpler form. Finally, it solves the simplified optimization problem using a branch-and-bound method." [see Constrained Optimization Tutorial in Mathematica.. ]

    I've written the following code that utilizes ILP libraries of Mathematica. It is surprisingly fast.

    solveMatrixBombProblem[problem_, r_, c_] := 
     Module[{}, 
      bombEffect[x_, y_, m_, n_] := 
       Table[If[(i == x || i == x - 1 || i == x + 1) && (j == y || 
            j == y - 1 || j == y + 1), 1, 0], {i, 1, m}, {j, 1, n}];
      bombMatrix[m_, n_] := 
       Transpose[
        Table[Table[
          Part[bombEffect[(i - Mod[i, n])/n + 1, Mod[i, n] + 1, m, 
            n], (j - Mod[j, n])/n + 1, Mod[j, n] + 1], {j, 0, 
           m*n - 1}], {i, 0, m*n - 1}]];
      X := x /@ Range[c*r];
      sol = Minimize[{Total[X], 
         And @@ Thread[bombMatrix[r, c].X >= problem] && 
          And @@ Thread[X >= 0] && Total[X] <= 10^100 && 
          Element[X, Integers]}, X];
      Print["Minimum required bombs = ", sol[[1]]];
      Print["A possible solution = ", 
       MatrixForm[
        Table[x[c*i + j + 1] /. sol[[2]], {i, 0, r - 1}, {j, 0, 
          c - 1}]]];]
    

    For the example provided in the problem:

    solveMatrixBombProblem[{2, 3, 4, 7, 1, 1, 5, 2, 6, 2, 4, 3, 4, 2, 1, 2, 1, 2, 4, 1, 3, 1, 3, 4, 1, 2, 1, 4, 3, 2, 6, 9, 1, 6, 4}, 7, 5]
    

    Outputs

    enter image description here

    For anyone reading this with a greedy algorithm

    Try your code on the following 10x10 problem:

    5   20  7   1   9   8   19  16  11  3  
    17  8   15  17  12  4   5   16  8   18  
    4   19  12  11  9   7   4   15  14  6  
    17  20  4   9   19  8   17  2   10  8  
    3   9   10  13  8   9   12  12  6   18  
    16  16  2   10  7   12  17  11  4   15  
    11  1   15  1   5   11  3   12  8   3  
    7   11  16  19  17  11  20  2   5   19  
    5   18  2   17  7   14  19  11  1   6  
    13  20  8   4   15  10  19  5   11  12
    

    Here it is comma-seperated:

    5, 20, 7, 1, 9, 8, 19, 16, 11, 3, 17, 8, 15, 17, 12, 4, 5, 16, 8, 18, 4, 19, 12, 11, 9, 7, 4, 15, 14, 6, 17, 20, 4, 9, 19, 8, 17, 2, 10, 8, 3, 9, 10, 13, 8, 9, 12, 12, 6, 18, 16, 16, 2, 10, 7, 12, 17, 11, 4, 15, 11, 1, 15, 1, 5, 11, 3, 12, 8, 3, 7, 11, 16, 19, 17, 11, 20, 2, 5, 19, 5, 18, 2, 17, 7, 14, 19, 11, 1, 6, 13, 20, 8, 4, 15, 10, 19, 5, 11, 12
    

    For this problem, my solution contains 208 bombs. Here's a possible solution (I was able to solve this in about 12 seconds).

    enter image description here

    As a way to test the results Mathematica is producing, see if your greedy algorithm can do any better.

提交回复
热议问题