Cake slicing

Cake slicing


题意:

n*m的方格中有k个点,现在要把方格切开使每个点在一个部分。

对于一个长方形来说,有从它的长切开和从它的宽切开两种选择,每切一次花费边长的费用,求完成要求所花的最小费用

解法:

d p [ s x ] [ s y ] [ e x ] [ e y ] dp[sx][sy][ex][ey] dp[sx][sy][ex][ey]表示要把起点坐标(sx,sy),终点坐标(ex,ey)的矩形切开的最小花费

  • 矩形内有0个点,则花费为INF

  • 矩形内有1个点,花费为0

  • 矩形内有>2个点

    d p [ s x ] [ s y ] [ e x ] [ e y ] ( 按 长 切 开 ) = m i n ( d p [ s x ] [ s y ] [ i ] [ e y ] + d p [ i ] [ s y ] [ e x ] [ e y ] + e x − s x ) dp[sx][sy][ex][ey](按长切开)=min(dp[sx][sy][i][ey]+dp[i][sy][ex][ey]+ex-sx) dp[sx][sy][ex][ey]()=min(dp[sx][sy][i][ey]+dp[i][sy][ex][ey]+exsx)

    d p [ s x ] [ s y ] [ e x ] [ e y ] ( 按 宽 切 开 ) = m i n ( d p [ s x ] [ s y ] [ e x ] [ j ] + d p [ s x ] [ j ] [ e x ] [ e y ] + e y − s y ) dp[sx][sy][ex][ey](按宽切开)=min(dp[sx][sy][ex][j]+dp[sx][j][ex][ey]+ey-sy) dp[sx][sy][ex][ey]()=min(dp[sx][sy][ex][j]+dp[sx][j][ex][ey]+eysy)

    ∀ i ∈ ( s x , e x ) , ∀ j ∈ ( s y , e y ) \forall i \in(sx,ex),\forall j \in(sy,ey) i(sx,ex)j(sy,ey)

代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const int maxm=20+10;
const int INF=1e7;
int n,m,k;
int dp[maxm][maxm][maxm][maxm];
int map[maxm][maxm];
int judge(int sx,int sy,int ex,int ey){
	int res=0;
	for(int i=sx+1;i<=ex;i++){
		for(int j=sy+1;j<=ey;j++){
			if(map[i][j]) res++;
			if(res==2) return 2;
		}
	}
	return res;
}
int DP(int sx,int sy,int ex,int ey){
	if(dp[sx][sy][ex][ey]!=-1) return dp[sx][sy][ex][ey];
	if(judge(sx,sy,ex,ey)==0) return dp[sx][sy][ex][ey]=INF;
	if(judge(sx,sy,ex,ey)==1) return dp[sx][sy][ex][ey]=0;
	int &tmp=dp[sx][sy][ex][ey];
	tmp=INF;
	for(int i=sx+1;i<ex;i++){
		tmp=min(tmp,DP(sx,sy,i,ey)+DP(i,sy,ex,ey)+ey-sy);
	}
	for(int i=sy+1;i<ey;i++){
		tmp=min(tmp,DP(sx,sy,ex,i)+DP(sx,i,ex,ey)+ex-sx);
	}
	return tmp;
}
int main(){
	int kase=0;
	while(~scanf("%d%d%d",&n,&m,&k)){
		memset(map,0,sizeof(map));
		memset(dp,-1,sizeof(dp));
		for(int i=0;i<k;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			map[x][y]=1;
		}
		printf("Case %d: %d\n",++kase,DP(0,0,n,m));
	}
}
注意要点:

Ⅰ:

记忆化(int DP()中的前三行)

Ⅱ:

矩形分割处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值