习题9-3(切蛋糕)【深搜dfs】+【记忆化搜索】

习题9-3

【UVa 1629】Cake Slicing(切蛋糕)

题目大意:

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

思路:

刚看到这道题的时候因为有了前两题的经验就往记忆化搜索那边靠,一下就想到了搜索思路:dp[x][y][xlen][ylen]表示以(x,y)为起点的分别以xlen,ylen为边长的矩形区域的最优解,这样就可以横着切每条网格线和纵着切每条网格线,对于每个搜索到的区域,如果之前没访问过,那么首先要判断此区域是否存在樱桃,有几个,如果没有则可以直接返回一个极大值抛弃这种情况,如果只有一个那就是末状态了,返回0,表明这一块的最小值为0,如果有多于1个,继续切割,每次转移时考虑切下来的两块的最优值加上切这一刀的花费。
转移方程:dfs(x,y,xlen,ylen)=min(dfs(x,y,xlen,ylen),dfs(x,y,i-x+1,ylen)+ylen+dfs(i+1,y,xlen-(i-x+1),ylen),dfs(x,y,xlen,j-y+1)+xlen+dfs(x,j+1,xlen,ylen-(j-y+1)));

tips:在dfs时可以用一个引用代表dp[][][][],既可省力又能使代码美观

代码:

#include
#include
#include
#include
using namespace std;
#define N 25

int m,n,k,dp[N][N][N][N],map[N][N],kase=0;
//dp(x,y,xlen,ylen)表示在以(x,y)为左上角,xlen,ylen为边长的区域内的切割最小值 

void init(){
    memset(map,0,sizeof(map));

    for(int i=1;i<=m;i++)//初始化dp数组为无穷大 
    for(int j=1;j<=n;j++)
    for(int o=1;o<=m;o++)
    for(int p=1;p<=n;p++)
        dp[i][j][o][p]=1000;

    int x,y;
    for(int i=1;i<=k;i++){
            cin>>x>>y;//记录cherry位置 
            map[x][y]=1;
    }

}

int dfs(int x,int y,int xlen,int ylen){//区域的左上角坐标(x,y),区域边长xlen和ylen 
    int& d = dp[x][y][xlen][ylen];
    if(d!=1000) return d;//已经查找过的就直接返回 

    int cut=0;
    for(int i=x;i<=x+xlen-1;i++)
    for(int j=y;j<=y+ylen-1;j++)
            if(map[i][j]) cut++;//判断此区域内有多少cherry 

    if(cut)
        if(cut==1){//只有一个就直接返回 
            return d=0;
        }else{//有一个以上就要继续切 
            for(int i=x;i<=x+xlen-2;i++)//横着切x~x+xlen-2 
                d=min(d,dfs(x,y,i-x+1,ylen)+ylen+dfs(i+1,y,xlen-(i-x+1),ylen));
            for(int j=y;j<=y+ylen-2;j++)//纵向切y~y+ylen-2
                d=min(d,dfs(x,y,xlen,j-y+1)+xlen+dfs(x,j+1,xlen,ylen-(j-y+1))); 
        }
    else//没有就舍弃这种情况 
        return d=2000;

    return d;
}

int main(){
    //freopen("2.txt","w",stdout);
    while(cin>>m>>n>>k){
        init();
        cout<< "Case " << ++kase << ": " <1,1,m,n)<return 0;
} 

后记:

开始做动态规划以来最流畅的一题,思路清晰,而且一次AC,爽快O(∩_∩)O~
ヽ(✿゚▽゚)ノ✧(≖ ◡ ≖✿)

你可能感兴趣的:(紫书第九章)