UVa 1629 切蛋糕(记忆化搜索)

https://vjudge.net/problem/UVA-1629

题意:

有一个n行m列的网格蛋糕上有一些樱桃。每次可以用一刀沿着网格线把蛋糕切成两块,并且只能直切不能拐弯。要求最后每一块蛋糕上恰好有一个樱桃且切割线总长度最小。

 

思路:

记忆化搜索。

d[u][d][l][r]表示这个范围内最少还需要切割多少长度。题目不难,代码很容易懂。

 1 #include<iostream> 
 2 #include<string>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 
 8 const int INF = 1000000;
 9 
10 int n, m, t;
11 int map[25][25];
12 int dp[25][25][25][25];
13 
14 
15 int cacl(int u, int d, int l, int r)
16 {
17     int cnt = 0;
18     for (int i = u + 1; i <= d; i++)
19     {
20         for (int j = l + 1; j <= r; j++)
21         {
22             if (map[i][j])  cnt++;
23             if (cnt == 2)      return 2;   //如果已经还有2个樱桃,说明还是要切割的
24         }
25     }
26     if (cnt == 1)     return 1;
27     else   return 0;
28 }
29 
30 int dfs(int u, int d, int l, int r)
31 {
32     int& ans = dp[u][d][l][r];
33     if (ans)        return ans;
34     ans = INF;    //初始化为无穷大
35     int tot = cacl(u, d, l, r);
36     if (tot == 1)   return ans = 0;     //如果只有一个樱桃,不需要切割了
37     if (tot == 0)    return INF;         //没有樱桃说明切割无效
38     //水平切割
39     for (int i = u + 1; i < d; i++)     
40         ans = min(dfs(u, i, l, r) + dfs(i, d, l, r) + r - l, ans);
41     //垂直切割
42     for (int i = l + 1; i < r; i++)
43         ans = min(dfs(u, d, l, i) + dfs(u, d, i, r) + d - u, ans);
44     return ans;
45 }
46 
47 int main()
48 {
49     //freopen("D:\\txt.txt", "r", stdin);
50     int kase = 0;
51     while (cin >> n >> m >> t)
52     {
53         memset(map, 0, sizeof(map));
54         memset(dp, 0, sizeof(dp));
55         int x, y;
56         for (int i = 0; i < t; i++)
57         {
58             cin >> x >> y;
59             map[x][y] = 1;
60         }
61         cout << "Case " << ++kase << ": " << dfs(0, n, 0, m) << endl;
62     }
63     return 0;
64 }

 

posted @ 2017-02-08 15:06  Kayden_Cheung  阅读(235)  评论(0编辑  收藏  举报
//目录