[ABC233G] Strongest Takahashi

Problem Statement

There is a N×N grid, with blocks on some squares.
The grid is described by N strings S1,S2,,SN, as follows.

  • If the j-th character of Si is #, there is a block on the square at the i-th row from the top and j-th column from the left.
  • If the j-th character of Si is ., there is not a block on the square at the i-th row from the top and j-th column from the left.

Takahashi can do the operation below zero or more times.

  • First, choose an integer D between 1 and N (inclusive), and a D×D subsquare within the grid.
  • Then, consume D stamina points to destroy all blocks within the subsquare.

Find the minimum number of stamina points needed to destroy all the blocks.

Constraints

  • N is an integer.
  • 1N50
  • Si consists of # and ..
  • |Si|=N

Input

Input is given from Standard Input in the following format:

$N$
$S_1$
$S_2$
$\vdots$
$S_N$

Output

Print the answer as an integer.


Sample Input 1

5
##...
.##..
#.#..
.....
....#

Sample Output 1

4

By choosing the subsquares below, Takahashi will consume 4 stamina points, which is optimal.

  • The 3×3 subsquare whose top-left square is at the 1-st row from the top and 1-st column from the left.
  • The 1×1 subsquare whose top-left square is at the 5-th row from the top and 5-th column from the left.

Sample Input 2

3
...
...
...

Sample Output 2

0

There may be no block on the grid.


Sample Input 3

21
.....................
.....................
...#.#...............
....#.............#..
...#.#...........#.#.
..................#..
.....................
.....................
.....................
..........#.....#....
......#..###.........
........#####..#.....
.......#######.......
.....#..#####........
.......#######.......
......#########......
.......#######..#....
......#########......
..#..###########.....
.........###.........
.........###.........

Sample Output 3

19

50的数据范围,基本上高次dp或者折半搜索的。这题不太像折半搜索,那就试一下高维dp。

定义 dpx1,y1,x2,y2 为解决以 (x1,y1) 为左上角,以 (x2,y2) 为右下角矩形 所需的最小代价.

首先肯定有一种 max(y2y1+1,x2x1+1) 的方案,那就是把他填满。

有一个引理,在我们填的矩阵中,一定不可能接壤,不然的话就可以选一个更大的矩阵,在代价一样的情况下框住的面积更大了。

所以如果不是全选的话,一定可以沿着某一行或者某一列把大矩阵割成两个矩阵解决。枚举对应的这一行或一列,递归下去就行了

这个dp的顺序应该按照区间dp的顺序。

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int n,dp[N][N][N][N],c1[N][N],c2[N][N],r1,r2;
char s[N][N];
void tomax(int&a,int b) 
{
	a=min(a,b);
}
int main() 
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			c1[i][j]=c1[i][j-1]+(s[i][j]=='#');
			c2[i][j]=c2[i-1][j]+(s[i][j]=='#');
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int l1=1;l1+i-1<=n;l1++)
			{
				for(int l2=1;l2+j-1<=n;l2++)
				{
					r1=l1+i-1,r2=l2+j-1;
					dp[l1][l2][r1][r2]=max(i,j);
					for(int k=l1;k<=r1;k++)
						if(c1[k][r2]==c1[k][l2-1])
							tomax(dp[l1][l2][r1][r2],dp[l1][l2][k-1][r2]+dp[k+1][l2][r1][r2]);
					for(int k=l2;k<=r2;k++)
						if(c2[l1-1][k]==c2[r1][k])
							tomax(dp[l1][l2][r1][r2],dp[l1][l2][r1][k-1]+dp[l1][k+1][r1][r2]);
//					printf("%d %d %d %d %d\n",l1,l2,r1,r2,dp[l1][l2][r1][r2]);
				}
			}
		}
	}
	printf("%d",dp[1][1][n][n]);
}
posted @   灰鲭鲨  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示