CF1199F Rectangle Painting 1

一、题意

给定一个 𝑛 × 𝑛 大小的方格图,每个方格一开始是黑色或者白色。每次可以选定一个\(h\times w\)的矩形将其中方格都涂成白色,代价是 \(max(h,w)\) 。求最小代价

输入:

第一行包含一个整数 \(n \;( 1≤n≤50 )\) — 正方形网格的大小。

接下来的 \(n\) 行都包含一个长度为 \(n\) 的字符串,由字符 ". " 和 "#" 组成。如果坐标为 \((i,j)\) 的单元格为黑色,则 i 行第 j 列的字符为'#',否则为白色。

二、分析

选定一个\(h\times w\)的矩形涂成白色,代价是 \(max(h,w)\;\Rightarrow\) 尽可能选正方形去覆盖

将矩形切割,分成形式相同规模更小的子问题,切割一次,染色代价是切割出来的矩阵的边长的最大值,对这个矩阵继续切割,最小代价一定 \(\leq\) 这个矩阵的边长的最大值,可以对 \(x,y\)做切割

三、方法

\(f[x_1][y_1][x_2][y_2]\) 表示矩阵 \((x_1,y_1)\)\((x_2,y_2)\) 这个范围染成白色的最小代价

初始代价为 \(max(x_2-x_1,y_2-y_1)\) ,继续切割 x、y,得到的最小代价一定 \(\leq\) 初始值

切割 x :

\[f[x1][y1][x2][y2]=min(f[x1][y1][x2][y2],f[x1][y1][k][y2]+f[k+1][y1][x2][y2]) \]

切割 y :

\[f[x1][y1][x2][y2]=min(f[x1][y1][x2][y2],f[x1][y1][x2][k]+f[x1][k+1][x2][y2]) \]

#include<bits/stdc++.h>
using namespace std;
int n,f[55][55][55][55]; 
char a[55][55];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cin>>a[i][j];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(a[i][j]=='.') f[i][j][i][j]=0;
			else f[i][j][i][j]=1;
		}
	}
	for(int lx=1;lx<=n;lx++){
		for(int ly=1;ly<=n;ly++){
			for(int x1=1;x1+lx-1<=n;x1++){
				for(int y1=1;y1+ly-1<=n;y1++){
					int x2=x1+lx-1;
					int y2=y1+ly-1;
					if(x1==x2&&y1==y2) continue;
					f[x1][y1][x2][y2]=max(x2-x1,y2-y1)+1;
					for(int k=x1;k<x2;k++) 
						f[x1][y1][x2][y2]=min(f[x1][y1][x2][y2],f[x1][y1][k][y2]+f[k+1][y1][x2][y2]);
					for(int k=y1;k<y2;k++) 
						f[x1][y1][x2][y2]=min(f[x1][y1][x2][y2],f[x1][y1][x2][k]+f[x1][k+1][x2][y2]);
				}
			}
		}
	}
	cout<<f[1][1][n][n]<<'\n';
	return 0;
}
posted @ 2026-06-13 10:30  Aguanenti  阅读(4)  评论(0)    收藏  举报