P1169 [ZJOI2007] 棋盘制作

链接

https://www.luogu.com.cn/problem/P1169

思路

刚开始想用类似深搜的方法:搜到一个块,然后用扫描线。 结果感觉太麻烦

(而且没有用到标签的dp),看了下题解用的是悬线法
(和扫描线也差不多嘛)
大概的思路就是通过计算一个点向左最多能达到多远,向右最多能达到多远,向上最多能达到多远来计算。关键的公式:

这其实是预处理,然后通过从上往下进行dp就行了

代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long

const int N = 2e3 + 10;
int mp[N][N];
int n, m;
int lef[N][N], rig[N][N], up[N][N];


signed main()
{
	IOS;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> mp[i][j];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			lef[i][j] = rig[i][j] = j;
	for(int i=1;i<=n;i++)
		for (int j = 2; j <= m; j++)
			if(mp[i][j]!=mp[i][j-1])
				lef[i][j] = min(lef[i][j], lef[i][j - 1]);
	for (int i = 1; i <= n; i++)
		for (int j = m - 1; j >= 1; j--)
			if (mp[i][j] != mp[i][j + 1])
				rig[i][j] = max(rig[i][j], rig[i][j + 1]);
	int matrixS = 1, squareS = 1;
	for (int j = 1; j <= m; j++)
	{
		up[1][j] = 1;
		matrixS = max(matrixS, (rig[1][j] - lef[1][j]+1));
	}
	for (int i = 2; i <= n; i++)
		for (int j = 1; j <= m; j++)
		{
			if (mp[i][j] != mp[i - 1][j])
			{
				up[i][j] = up[i - 1][j] + 1;
				lef[i][j] = max(lef[i - 1][j], lef[i][j]);
				rig[i][j] = min(rig[i][j], rig[i - 1][j]);
			}
			else up[i][j] = 1;
			matrixS = max(matrixS, (rig[i][j] - lef[i][j]+1) * up[i][j]);
			squareS = max(squareS, (int)pow(min(rig[i][j] - lef[i][j]+1, up[i][j]), 2));
		}
	cout << squareS << '\n' << matrixS;


	return 0;
}
posted @   WHUStar  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示