[UVA 1629]Cake slicing[记忆化搜索]

来源:互联网 发布:2017淘宝摇一摇在哪里 编辑:程序博客网 时间:2024/05/20 00:37
题目链接:[UVA 1629]Cake slicing
题意分析:一个矩形蛋糕上有好多个樱桃,现在要做的就是切割最少的距离,切出矩形形状的小蛋糕,让每个蛋糕上都有一个樱桃~问最少切割距离是?

解题思路:既然是切割蛋糕,可以感受到是一个无限切割的过程(递归?)反正有这种感觉存在。然后数据是20*20。那么就试试记忆化搜索。我们设dp[u][d][l][r]为u(up)为上届d(down)为下界,l为左界,r为右界的最小切割距离。边界就是当整块区域只有一个樱桃显然不用切割了,返回0。当整块区域没有樱桃时,这块区域就是无效的切割,设置为无穷。

个人感受:舍友提醒可以暴力的一个一个切割,可是脑袋里一点感觉都没有,递归的想法一点都没有,要哭瞎了TAT最后看了别人的才豁然开朗= =
具体代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<algorithm>using namespace std;const int INF = 0x3f3f3f3f;int n, m, dp[25][25][25][25];bool has[25][25]; //记录格点是否有樱桃int sum(int u, int d, int l, int r) //统计区域的樱桃数{    int ret = 0;    for (int i = u + 1; i <= d; ++i)        for (int j = l + 1; j <= r; ++j)        {            if (has[i][j]) ++ret;            if (ret == 2) return 2; //超过两个也就是多个的情况可以统一递归处理,直接视为同一情况        }    return ret;}int dfs(int u, int d, int l, int r){    int &ret = dp[u][d][l][r];    if (ret != -1) return ret;    int total = sum(u,d,l,r);    if (total == 1) return ret = 0; //一个樱桃返回0,无需切割了    if (!total) return ret = INF;  //没有樱桃,无效切割    ret = INF;    for (int i = u + 1; i < d; ++i) //水平切割        ret = min(ret, dfs(u,i,l,r) + dfs(i,d,l,r) + r - l);    for (int i = l + 1; i < r; ++i) //垂直切割        ret = min(ret, dfs(u,d,l,i) + dfs(u,d,i,r) + d - u);    return ret;}int main(){    int k, x, y, kase = 0;    while(cin >> n >> m >> k)    {   memset(dp, -1, sizeof dp);   memset(has, 0, sizeof has);   for (int i = 0; i < k; ++i) cin >> x >> y, has[x][y] = 1;   cout << "Case " << ++kase << ": " << dfs(0, n, 0, m) << '\n';    }return 0;}

0 0
原创粉丝点击