UVa 1629 Cake Slicing DP
2015-12-15 05:50
309 查看
这题空了好久,虽然现在想出来了很激动,但是花的时间略长呀。。。
每切一次蛋糕就相当于一次状态转移。设某时刻蛋糕的坐上顶点为(a, b),右下顶点为(c, d),将这块蛋糕切成只剩一个樱桃产生的切割线长度最短为d ( a, b, c, d)。
原来是想根据樱桃的位置来切蛋糕,但是很难实现。考虑到横竖共m + n 种切法,可以枚举状态。
纵向:min { d ( a, b, c, j ) + d ( a, j + 1, c, d ) + d - b + 1 } ( b <= j < d )
横向:min { d ( a, b, i, d ) + d ( i + 1, b, c, d ) + c - a + 1 } ( a <= i < c )
枚举时需要判断:当矩形内只有一个点时,d() 值为0;当切割出的矩形不含樱桃时,舍弃此种情况。d[][][][]初始化为-1。
代码:
每切一次蛋糕就相当于一次状态转移。设某时刻蛋糕的坐上顶点为(a, b),右下顶点为(c, d),将这块蛋糕切成只剩一个樱桃产生的切割线长度最短为d ( a, b, c, d)。
原来是想根据樱桃的位置来切蛋糕,但是很难实现。考虑到横竖共m + n 种切法,可以枚举状态。
纵向:min { d ( a, b, c, j ) + d ( a, j + 1, c, d ) + d - b + 1 } ( b <= j < d )
横向:min { d ( a, b, i, d ) + d ( i + 1, b, c, d ) + c - a + 1 } ( a <= i < c )
枚举时需要判断:当矩形内只有一个点时,d() 值为0;当切割出的矩形不含樱桃时,舍弃此种情况。d[][][][]初始化为-1。
代码:
#include <cstdio> #include <cstring> const int maxn = 25; int n, m, k; int dp[maxn][maxn][maxn][maxn], rec[maxn][maxn]; int dpl(int a, int b, int c, int d) { if (dp[a][b][c][d] > -1) return dp[a][b][c][d]; int &res = dp[a][b][c][d]; int dot = rec[c][d] + rec[a - 1][b - 1] - rec[a - 1][d] - rec[c][b - 1]; //printf("1:%d,%d %d,%d value:%d\n", a, b, c, d, res); if (dot == 1) return res = 0; int min = 1000000; for (int j = b; j < d; j++) { // divide into d(a, b, c, j) and d(a, j + 1, c, d) dot = rec[c][j] + rec[a - 1][b - 1] - rec[a - 1][j] - rec[c][b - 1]; if (dot == 0) continue; dot = rec[c][d] + rec[a - 1][j] - rec[a - 1][d] - rec[c][j]; if (dot == 0) continue; int t = dpl(a, b, c, j) + dpl(a, j + 1, c, d) + c - a + 1; if (t < min) min = t; } for (int i = a; i < c; i++) { // divide into d(a, b, i, d) and d(i + 1, b, c, d) dot = rec[i][d] + rec[a - 1][b - 1] - rec[a - 1][d] - rec[i][b - 1]; if (dot == 0) continue; dot = rec[c][d] + rec[i][b - 1] - rec[i][d] - rec[c][b - 1]; if (dot == 0) continue; int t = dpl(a, b, i, d) + dpl(i + 1, b, c, d) + d - b + 1; if (t < min) min = t; } res = min; //printf("2:%d,%d %d,%d value:%d\n", a, b, c, d, res); return res; } int main() { #ifndef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int kase = 1; while (~scanf("%d%d%d", &n, &m, &k)) { memset(rec, 0, sizeof(rec)); memset(dp, -1, sizeof(dp)); int x, y; for (int i = 0; i < k; i++) { scanf("%d%d", &x, &y); rec[x][y] = 1; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { rec[i][j] += rec[i - 1][j]; //printf("%d%c", rec[i][j], " \n"[j == m]); } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { rec[i][j] += rec[i][j - 1]; //printf("%d%c", rec[i][j], " \n"[j == m]); } printf("Case %d: %d\n", kase++, dpl(1, 1, n, m)); } return 0; }
相关文章推荐
- CPP-Templates
- 物联网碰壁后,这位创业者总结失败五大原因
- “达克效应”让人们信心满满还是畏惧不前?- 更应该是谨慎地冒险
- BugPhobia开发篇章:Beta阶段第II次Scrum Meeting
- BugPhobia开发篇章:Beta阶段第II次Scrum Meeting
- 普法知识(36):软件著作权人
- Android 的 SQLLite数据库
- Dalvik和ART
- (转) External Sort
- STM32的内核CM3没有理解,NVIC,EXTI都涉及到了,内核到目前为止没有理解
- 你真的了解word-wrap和word-break的区别吗?
- Utilize Avahi Libraries in Android for mDNS Discovering
- urdf 学习笔记一
- Linux_VMWare12 Install RHEL7
- FFMPEG支持的所有编码解码
- Common JS String Methods
- 数据结构串
- Leetcode: Count Primes
- 变量生命周期
- IOS中在自定义控件(非视图控制器)的视图跳转中 代理方法与代码块的比较