• UVA 1629


      记忆化搜索, 枚举所有的切割方式dp[r1][c1][r2][c2]表示(r1, c1) (r2, c2)之间的蛋糕切割所需要的最小花费count_num用来计算(r1, c1) (r2, c2)之间有多少个草莓递推边界当count_num为1是返回0

      init()为对草莓数的一个预处理,使得在O(1)的时间内可以计算区域内的草莓数

      总状态数为m * n * m * n决策有n + m种
      时间复杂度为O((n + m) * n * n * m * m)

    /*583ms*/
    1
    #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<map> 6 #include<set> 7 #include<vector> 8 #include<queue> 9 #include<iostream> 10 #define PB push_back 11 #define POB pop_back 12 #define PII pair<int, int> 13 #define PDD pair<double, double> 14 #define rep(i, a, b) for(int i = a ; i < b ; i++) 15 #pragma comment(linker, "/STACK:1024000000,1024000000") 16 #ifdef WIN32 17 #define INT64 "%I64d" 18 #define UINT64 "%I64u" 19 #else 20 #define INT64 "%lld" 21 #define UINT64 "%llu" 22 #endif 23 typedef long long LL; 24 typedef unsigned long long ULL; 25 using namespace std; 26 const int maxn = 22; 27 const int INF = 0x3f3f3f3f; 28 int dp[maxn][maxn][maxn][maxn]; 29 int cou[maxn][maxn]; 30 int n, m, k; 31 void init() { 32 for(int i = 1 ; i <= n ; i++) 33 for(int j = 2 ; j <= m ; j++) 34 cou[i][j] += cou[i][j - 1]; 35 for(int i = 2; i <= n ; i++) 36 for(int j = 1 ; j <= m ; j++) 37 cou[i][j] += cou[i - 1][j]; 38 } 39 int count_num(int r1, int c1, int r2, int c2) { 40 int a = cou[r2][c1 - 1]; 41 int b = cou[r1 - 1][c2]; 42 int c = cou[r1 - 1][c1 - 1]; 43 return cou[r2][c2] - a - b + c; 44 } 45 int DP(int r1, int c1, int r2, int c2) { 46 int& cnt = dp[r1][c1][r2][c2]; 47 if(cnt != INF) return cnt; 48 if(count_num(r1, c1, r2, c2) == 1) return cnt = 0; 49 for(int i = r1 ; i < r2 ; i++) { //ºá×ÅÇÐ 50 int num1 = count_num(r1, c1, i, c2); 51 int num2 = count_num(i + 1, c1, r2, c2); 52 if(num1 == 0 || num2 == 0) continue; 53 cnt = min(cnt, DP(r1, c1, i, c2) + DP(i + 1, c1, r2, c2) + c2 - c1 + 1); 54 } 55 for(int i = c1 ; i < c2 ; i++) { 56 int num1 = count_num(r1, c1, r2, i); 57 int num2 = count_num(r1, i + 1, r2, c2); 58 if(num1 == 0 || num2 == 0) continue; 59 cnt = min(cnt, DP(r1, c1, r2, i) + DP(r1, i + 1, r2, c2) + r2 - r1 + 1); 60 } 61 return cnt; 62 } 63 int main() 64 { 65 int ca(1); 66 while(scanf("%d%d%d", &n, &m, &k) == 3) { 67 if(k == 0) { 68 printf("Case %d: %d ", ca++, 0); 69 } 70 memset(dp, 0x3f, sizeof dp); 71 memset(cou, 0, sizeof cou); 72 for(int i = 0 ; i < k ; i++) { 73 int x, y; scanf("%d%d", &x, &y); 74 cou[x][y] = 1; 75 } 76 init(); 77 printf("Case %d: %d ", ca++, DP(1, 1, n, m)); 78 } 79 return 0; 80 }
  • 相关阅读:
    Word Break
    Binary Tree Right Side View
    41. First Missing Positive
    2 Sum ,3 Sum, 3 Sum close
    216. Combination Sum III
    190. Reverse Bits
    143. Reorder List
    142. Linked List Cycle II
    Single Number i,ii,iii
    62. Unique Paths i & ii
  • 原文地址:https://www.cnblogs.com/tooyoungtoosimple/p/4773857.html
Copyright © 2020-2023  润新知