Advertisement
erek1e

IOI '09 P4 - Raisins

Jul 10th, 2023
908
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.36 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. using namespace std;
  5.  
  6. const int INF = 1e9;
  7.  
  8. int main() {
  9.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  10.     int n, m; cin >> n >> m;
  11.     vector<vector<int>> a(1+n, vector<int>(1+m));
  12.     for (int i = 1; i <= n; ++i) {
  13.         for (int j = 1; j <= m; ++j) cin >> a[i][j];
  14.     }
  15.     vector<vector<int>> pre = a;
  16.     for (int i = 1; i <= n; ++i) {
  17.         for (int j = 1; j <= m; ++j) pre[i][j] += pre[i][j-1];
  18.         for (int j = 1; j <= m; ++j) pre[i][j] += pre[i-1][j];
  19.     }
  20.     auto rangeSum = [&](int top, int bottom, int left, int right) {
  21.         --top, --left;
  22.         return pre[bottom][right] - pre[bottom][left] - pre[top][right] + pre[top][left];
  23.     };
  24.  
  25.     // dp with O((nm)^2) states, and O(n+m) transitions for each state
  26.     vector<vector<vector<vector<int>>>> minCost(1+n, vector<vector<vector<int>>>(1+n, vector<vector<int>>(1+m, vector<int>(1+m, INF))));
  27.     // in order of increasing size
  28.     for (int height = 1; height <= n; ++height) {
  29.         for (int width = 1; width <= m; ++width) {
  30.             for (int top = 1, bottom = height; bottom <= n; ++top, ++bottom) {
  31.                 for (int left = 1, right = width; right <= m; ++left, ++right) {
  32.                     // find minCost[top][bottom][left][right]
  33.                     int cutCost = rangeSum(top, bottom, left, right);
  34.                     int &cur = minCost[top][bottom][left][right];
  35.                     if (height == 1 && width == 1) {
  36.                         cur = 0;
  37.                         continue;
  38.                     }
  39.                    
  40.                     // try a horizontal cut
  41.                     for (int middle = top+1; middle <= bottom; ++middle) {
  42.                         int x = minCost[top][middle-1][left][right];
  43.                         int y = minCost[middle][bottom][left][right];
  44.                         cur = min(cur, cutCost + x + y);
  45.                     }
  46.  
  47.                     // try a vertical cut
  48.                     for (int middle = left+1; middle <= right; ++middle) {
  49.                         int x = minCost[top][bottom][left][middle-1];
  50.                         int y = minCost[top][bottom][middle][right];
  51.                         cur = min(cur, cutCost + x + y);
  52.                     }
  53.                 }
  54.             }
  55.         }
  56.     }
  57.     cout << minCost[1][n][1][m] << endl;
  58.     return 0;
  59. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement