A rectangular cake with a grid of m*n unit squares on its top needs to be sliced into pieces. Several cherries are scattered on the top of the cake with at most one cherry on a unit square. The slicing should follow the rules below:
1. each piece is rectangular or square;
2. each cutting edge is straight and along a grid line;
3. each piece has only one cherry on it;
4. each cut must split the cake you currently cut two separate parts
For example, assume that the cake has a grid of 3*4 unit squares on its top, and there are three cherries on the top, as shown in the figure below.
One allowable slicing is as follows.
For this way of slicing , the total length of the cutting edges is 2+4=6.
Another way of slicing is
In this case, the total length of the cutting edges is 3+2=5.
Give the shape of the cake and the scatter of the cherries , you are supposed to find
out the least total length of the cutting edges.
1. each piece is rectangular or square;
2. each cutting edge is straight and along a grid line;
3. each piece has only one cherry on it;
4. each cut must split the cake you currently cut two separate parts
For example, assume that the cake has a grid of 3*4 unit squares on its top, and there are three cherries on the top, as shown in the figure below.
![](https://i-blog.csdnimg.cn/blog_migrate/79e06861e45184b2c9cc654c30a99139.jpeg)
One allowable slicing is as follows.
![](https://i-blog.csdnimg.cn/blog_migrate/3ffeb5a8ad73eb78fb83e79e086251d7.jpeg)
For this way of slicing , the total length of the cutting edges is 2+4=6.
Another way of slicing is
![](https://i-blog.csdnimg.cn/blog_migrate/db000a40cd2184c524536939a661d1b1.jpeg)
In this case, the total length of the cutting edges is 3+2=5.
Give the shape of the cake and the scatter of the cherries , you are supposed to find
out the least total length of the cutting edges.
Input
The input file contains multiple test cases. For each test case:
The first line contains three integers , n, m and k (1≤n, m≤20), where n*m is the size of the unit square with a cherry on it . The two integers show respectively the row number and the column number of the unit square in the grid .
All integers in each line should be separated by blanks.
The first line contains three integers , n, m and k (1≤n, m≤20), where n*m is the size of the unit square with a cherry on it . The two integers show respectively the row number and the column number of the unit square in the grid .
All integers in each line should be separated by blanks.
Output
Output an integer indicating the least total length of the cutting edges.
Sample Input
3 4 3 1 2 2 3 3 2
Sample Output
Case 1: 5
看到这题目的输入最大数据是20我感到了深深的恶意。。。结果在uva上wa了一次之后我发现要用4维数组,再wa一次之后我发现切割的时候要排除不能切割的方法,终于AC(话说我拉低了那题的AC率ORZ)。主题思路是用dp[i][i1][j][j1]代表从i~i1 j~j1这些方格中要切割的长度,如果这些方格中没有蛋糕,就把dp[i][i1][j][j1]赋值为-1,表示不能切割,如果有一个蛋糕就赋值为0,表示不需要切割,如果超过两个蛋糕那么就决定第一刀怎么切,横纵两种方式多种方法枚举就可以。就这样吧,上代码了。
Case 1: 5
看到这题目的输入最大数据是20我感到了深深的恶意。。。结果在uva上wa了一次之后我发现要用4维数组,再wa一次之后我发现切割的时候要排除不能切割的方法,终于AC(话说我拉低了那题的AC率ORZ)。主题思路是用dp[i][i1][j][j1]代表从i~i1 j~j1这些方格中要切割的长度,如果这些方格中没有蛋糕,就把dp[i][i1][j][j1]赋值为-1,表示不能切割,如果有一个蛋糕就赋值为0,表示不需要切割,如果超过两个蛋糕那么就决定第一刀怎么切,横纵两种方式多种方法枚举就可以。就这样吧,上代码了。
#include <iostream>
#include <cstdio>
#include <cstring>
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 25;
int dp[maxn][maxn][maxn][maxn];
int n,m,cnt;
int G[maxn][maxn];
int ishavecake(int i , int i1 , int j , int j1) {
int cnt = 0;
for (int k = i ; k <= i1 ; k++) {
for (int s = j ; s <= j1 ; s++) {
if (G[k][s]) cnt++;
}
}
return cnt;
}
void solve () {
for (int ly = 1 ; ly <= n ; ly++) {
for (int i = 1 ; i <= n-ly+1 ; i++) {
int i1 = i+ly-1;
for (int lx = 1 ; lx <= m ; lx++) {
for (int j = 1 ; j <= m-lx+1 ; j++) {
int j1 = j+lx-1;
if (ishavecake(i,i1,j,j1) <= 1) {
dp[i][i1][j][j1] = ishavecake(i,i1,j,j1)-1;
continue;
}
int tmp1 = inf;
for (int div = i ; div <= i1-1 ; div++)
if (dp[i][div][j][j1] >= 0 && dp[div+1][i1][j][j1] >= 0)
tmp1 = min(tmp1 , dp[i][div][j][j1]+dp[div+1][i1][j][j1]+j1-j+1);
int tmp2 = inf;
for (int div = j ; div <= j1-1 ; div++)
if (dp[i][i1][j][div] >= 0 && dp[i][i1][div+1][j1] >= 0)
tmp2 = min(tmp2 , dp[i][i1][j][div]+dp[i][i1][div+1][j1]+i1-i+1);
dp[i][i1][j][j1] = min(tmp1 , tmp2);
}
}
}
}
}
int main () {
int s = 1;
while(cin >> n >> m >> cnt){
memset(G,0,sizeof(G));
memset(dp,0,sizeof(dp));
for (int i = 1 ; i <= cnt ; i++) {
int x , y;
cin >> x >> y;
G[x][y] = 1;
}
solve();
printf("Case %d: %d\n" , s++ , dp[1][n][1][m]);
}
}