UVA 1629 Cake slicing——记忆化搜索

来源:互联网 发布:手机网络切换开关 编辑:程序博客网 时间:2024/06/11 23:57

题意:给你一个蛋糕,蛋糕上有一些樱桃,要求寻找一种切法使得切完后每块蛋糕上恰好有一个樱桃,并且切割的总距离最短,每次切割只能沿着网格线把一块蛋糕横着切开或竖着切开。

思路:记忆化搜索,四维dp数组记录每块蛋糕的四个边界,每次枚举横竖的切割位置产生两个子问题,求出使两个子问题的和最小的那种切法。

坑点在于边界不好想,一开始用了一个四维的cnt数组想记录每个状态的樱桃数进行判断,发现无法用每块的樱桃数限制状态转移,然后想了想可以对边界进行特殊处理,每次记忆化开始先用for循环暴力记录当前蛋糕上的樱桃数,当数量为1时返回0,当数量为0时返回INF,其余情况继续记忆化,至于为什么要返回0或者INF参考状态转移方程

minv = min(minv, dfs(x,x,x,x) + dfs(x,x,x,x) + x -x);(这里的x参考代码)

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <queue>#include <map>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;int flag = 1, n, m, k, cake[25][25], dp[25][25][25][25];int dfs(int w, int s, int a, int d) {    if (dp[w][s][a][d] != -1) return dp[w][s][a][d];    int sum = 0;    for (int i = w; i < s; i++) {        for (int j = a; j < d; j++) {            if (cake[i][j]) sum++;        }    }    if (sum == 1) return 0;    if (sum == 0) return INF;    int minv = INF;    for (int i = w + 1; i < s; i++) {        minv = min(minv, dfs(w, i, a, d) + dfs(i, s, a, d) + d - a);    }    for (int i = a + 1; i < d; i++) {        minv = min(minv, dfs(w, s, a, i) + dfs(w, s, i, d) + s - w);    }    return dp[w][s][a][d] = minv;}int main(){    while (scanf("%d %d %d", &n, &m, &k) == 3) {        memset(cake, 0, sizeof(cake));        memset(dp, -1, sizeof(dp));        for (int i = 0; i < k; i++) {            int x, y; scanf("%d %d", &x, &y);            cake[x][y] = 1;        }        printf("Case %d: %d\n", flag++, dfs(1, n + 1, 1, m + 1));    }    return 0;}