您的位置:首页 > 其它

动态规划特训:切蛋糕(UVA1629)

2018-09-11 16:06 183 查看

解题思路:利用动态规划的思想,这里的状态即是蛋糕的上线、下线、左线、右线。然后进行记忆化搜素。遍历竖着切的每一种方式和横着切的每一种方式最终得到结果。状态转移方程稍微有些繁琐,在这里就不列举了,可以直接看代码理解。

题目大意:给定一个方形蛋糕,上面有一些樱桃,现在可以对该蛋糕做切割处理,保证切出来的每一份小蛋糕上都有一个樱桃,且切割线的总长度最小。

Sample Input
3 4 3
1 2
2 3
3 2
Sample Output
Case 1: 5

[code]#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf = 1 << 30;

int n, m, k, dp[51][51][51][51]; //蛋糕尺寸和樱桃数目,以及dp数值
bool mark[51][51];  //为true即表示该位置放有樱桃

int sum(int s, int x, int z, int y)  //此函数用来统计尺寸蛋糕内樱桃的数目
{
int ret = 0;
for (int i = x; i <= s; i++)
{
for (int j = z; j <= y; j++)
{
if (mark[i][j] == true) ret++;
}
}
return ret;
}

int f(int s, int x, int z, int y)
{
int &ans = dp[s][x][z][y];
if (ans != -1) return ans;
int cherry = sum(s, x, z, y);
if (cherry == 1) return ans = 0;   //如果尺寸内只有一个樱桃,则无需切割,直接返回0
ans = inf;
for (int i = x; i <s; i++)
{
if (sum(i, x, z, y) == 0 || sum(s, i + 1, z, y) == 0) continue;  //若选择的切割方式切不出樱桃,则放弃
ans = min(ans, f(i, x, z, y) + f(s, i + 1, z, y) + y - z+1);
}
for (int i = z;i < y; i++)
{
if (sum(s, x, z, i) == 0 || sum(s, x, i + 1, y) == 0) continue;  //同理,切出的蛋糕无樱桃则放弃
ans = min(ans, f(s, x, z, i) + f(s, x, i + 1, y) + s - x+1);
}
return ans;
}

int main()
{
while (cin >> n >> m)
{
cin >> k;
memset(mark, false, sizeof(mark));
memset(dp, -1, sizeof(dp));
for (int i = 1; i <= k; i++)
{
int x, y; cin >> x >> y;
mark[x][y] = true;
}
cout << f(n, 1, 1, m) << endl;
}
return 0;
}

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: