UVA 1629 Cake slicing 记忆化搜索

                                  Cake slicing

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.
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 on the right corner.
One allowable slicing is as follows.
For this way of slicing, the total length of the cutting edges is 4+2=6.
Another way of slicing is
In this case, the total length of the cutting edges is 3+2=5.
Given 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
grid on the cake, and k is the number of the cherries.
Then k lines follow. Each line has two integers indicating the position 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

 

题意:

 

  给你一个n行m列的网格,上面有一些蛋糕。每次可以用一刀沿着网格线切成两块,并且只能够直切不能拐弯。

  要求最后每一块蛋糕上恰好有一个樱桃,

  且切割线总长度最小。

 

题解:

  

  我们记忆花爆搜就好了

  设定dp[row][col][x][y] 在当前以点(x,y)为左上角的蛋糕块的最小切割次数,且保证分的块数尽量多

  我们接下来枚举切那个地方就好了

#include<bits/stdc++.h>
using namespace std;
const int N = 25, M = 100, inf = 1e9+7, mod = 1e9+7;
int T,n,m,k,mp[N][N],dp[N][N][N][N],vis[N][N][N][N];
int dfs(int row,int col,int x,int y) {
    if(vis[row][col][x][y]) return dp[row][col][x][y];
    int& ret = dp[row][col][x][y];
    ret = inf;
    vis[row][col][x][y] = 1;
    if(row==1&&col==1) {
        ret = mp[x][y]?0:inf;
        return ret;
    }
    int cnt = 0;
    for(int i=x;i<=row+x-1;i++)
        for(int j=y;j<=y+col-1;j++) if(mp[i][j]) cnt++;
    if(cnt == 1) {
        ret = 0;
        return ret;
    }
    if(cnt == 0) return ret;
    for(int i=y+1;i<=y+col-1;i++) {
        ret = min(ret,dfs(row,i-y,x,y)+dfs(row,col-i+y,x,i)+row);
    }
    for(int i=x+1;i<=x+row-1;i++) {
        ret = min(ret,dfs(i-x,col,x,y)+col+dfs(row-i+x,col,i,y));
    }
    return ret;
}
int main() {
    int x,y,cas = 1;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
        memset(mp,0,sizeof(mp));memset(dp,-1,sizeof(dp));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=k;i++) scanf("%d%d",&x,&y), mp[x][y] = 1;
        printf("Case %d: %d\n",cas++,dfs(n,m,1,1));
    }
    return 0;
}

 

posted @ 2016-04-26 22:55  meekyan  阅读(383)  评论(0编辑  收藏  举报