题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51190
紫书P305
题意分析:一个矩形蛋糕上有好多个樱桃,现在要做的就是切割最少的距离,切出矩形形状的小蛋糕,让每个蛋糕上都有一个樱桃,问最少切割距离是?
解题思路:既然是切割蛋糕,可以感受到是一个无限切割的过程(递归?)反正有这种感觉存在。然后数据是20*20。那么就试试记忆化搜索。我们设dp[u][d][l][r]为u(up)为上届d(down)为下界,l为左界,r为右界的最小切割距离。边界就是当整块区域只有一个樱桃显然不用切割了,返回0。当整块区域没有樱桃时,这块区域就是无效的切割,设置为无穷。
弱逼没点想法,看了大神的题解顿时恍然大悟
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 const int INF = 0x3f3f3f3f; 9 int n, m, dp[25][25][25][25]; 10 bool has[25][25]; //记录格点是否有樱桃 11 12 int sum(int u, int d, int l, int r) //统计区域内的樱桃数 13 { 14 int total = 0; 15 for(int i = u + 1; i <= d; i++) 16 { 17 for(int j = l + 1; j <= r; j++) 18 { 19 if(has[i][j]) 20 total++; 21 if(total == 2) //只要至少两个就得分割 22 return 2; 23 } 24 } 25 return total; 26 } 27 28 29 int dfs(int u, int d, int l, int r) 30 { 31 int &res = dp[u][d][l][r]; 32 if(res != -1) 33 return res; 34 int total = sum(u, d, l, r); 35 if(total == 1) 36 return res = 0; 37 if(total == 0) 38 return res = INF; 39 res = INF; // 找res的最小,要先把他设成最大值 40 for(int i = u + 1; i < d; i++) 41 res = min(res, dfs(u, i, l, r) + dfs(i, d, l, r) + (r - l)); //按行分割 42 for(int i = l + 1; i < r; i++) 43 res = min(res, dfs(u, d, l, i) + dfs(u, d, i, r) + d - u); //按列分割 44 return res; 45 } 46 int main() 47 { 48 int test = 0,k; 49 while(scanf("%d%d%d", &n, &m, &k) != EOF) 50 { 51 int x,y; 52 memset(has, 0, sizeof(has)); 53 memset(dp, -1, sizeof(dp)); 54 for(int i = 0; i < k; i++) 55 { 56 scanf("%d%d", &x, &y); 57 has[x][y] = 1; 58 } 59 printf("Case %d: %d ", ++test,dfs(0, n, 0, m)); //上开下闭的区间 60 } 61 return 0; 62 }