Codeforces1198 D. Rectangle Painting 1(记忆化爆搜)

题意:

给定nn的矩形,格子是黑色或者白色。
一次操作,你可以选择一个矩形,假设是h
w的,将他涂成白色,代价为max(h,w)
问将整个矩形涂成白色的最小代价。

数据范围:n<=50

解法:

d[x][y][xx][yy]表示这个矩形的最小代价

如果矩形全白,代价为0.
如果矩形全黑,代价为max(h,w),且可以证明分割成小矩形不会更优.
如果矩形黑白相间:
1.如果不拆代价为max(h,w).
2.如果拆,则枚举第一条分割点递归计算.
用记忆化搜索

code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef pair<int,int> PI;
const int maxm=55;
int sum[maxm][maxm];
char s[maxm][maxm];
ll d[maxm][maxm][maxm][maxm];
int a[maxm][maxm];
int n;
int cal(int x,int y,int xx,int yy){
    return sum[xx][yy]-sum[xx][y-1]-sum[x-1][yy]+sum[x-1][y-1];
}
ll dfs(int x,int y,int xx,int yy){
    if(d[x][y][xx][yy]!=-1)return d[x][y][xx][yy];
    int cnt=cal(x,y,xx,yy);
    if(cnt==0)return d[x][y][xx][yy]=0;//全白
    if(cnt==(yy-y+1)*(xx-x+1))return d[x][y][xx][yy]=max(yy-y+1,xx-x+1);//全黑
    ll ans=max(yy-y+1,xx-x+1);
    for(int i=x;i<=xx-1;i++){
        ans=min(ans,dfs(x,y,i,yy)+dfs(i+1,y,xx,yy));
    }
    for(int i=y;i<=yy-1;i++){
        ans=min(ans,dfs(x,y,xx,i)+dfs(x,i+1,xx,yy));
    }
    return d[x][y][xx][yy]=ans;
}
signed main(){
    memset(d,-1,sizeof d);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        for(int j=1;j<=n;j++){
            a[i][j]=(s[i][j]=='#');
        }
    }
    for(int i=1;i<=n;i++){//二维前缀和
        for(int j=1;j<=n;j++){
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
        }
    }
    ll ans=dfs(1,1,n,n);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107825766
今日推荐