uva 1629 cake slicing(dp)

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.
 

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.
 

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,表示不需要切割,如果超過兩個蛋糕那麼就決定第一刀怎麼切,橫縱兩種方式多種方法枚舉就可以。就這樣吧,上代碼了。

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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章