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.
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.
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]);
}
}