Atcoder agc033 D - Complexity

題面

題意

給出一個矩陣,若一個矩陣中的所有元素都相同,則這個矩陣的代價爲0,反之可以將它分成兩個子矩陣,代價爲兩個子矩陣的代價的較大值+1.

做法

因爲答案是log級別的,所以可以考慮枚舉答案,記dp[l][r][i]dp[l][r][i]從第l行到第r行從第i列開始最多可以向右擴展到哪一列所形成的矩陣的代價爲當前答案,若dp[1][n][1]=mdp[1][n][1]=m,則表示當前答案即爲整個矩形的代價.
ans=0ans=0時的答案很好處理,考慮如何將此時的答案轉移到ans+1時的答案.一個矩形有兩種拼接方法:
1.兩個所在行相同的相鄰矩形,直接轉移:dp[l][r][i]=dp[l][r][dp[l][r][i]]dp[l][r][i]=dp[l][r][dp[l][r][i]]
2.兩個所在列相同的相鄰矩形,dp[l][r][i]=maxx=lr1min(dp[l][x][i],dp[x+1][r][i])dp[l][r][i]=\max_{x=l}^{r-1}min(dp[l][x][i],dp[x+1][r][i]),這個可以通過二分找到最優解.

代碼

#include<bits/stdc++.h>
#define N 200
using namespace std;

int m,n,ans,dp[2][N][N][N];
char mm[N][N];
bool now,cur;

inline void Max(int &u,int v){if(v>u) u=v;}
int main()
{
	int i,j,p,q,l,r,mid;
	cin>>m>>n;
	for(i=1;i<=m;i++) scanf("%s",mm[i]+1);
	now=1;
	for(q=1;q<=m;q++)
	{
		for(p=q;p>=1;p--)
		{
			for(i=n;i>=1;i--)
			{
				if(p==q)
				{
					if(i==n) dp[now][p][q][i]=n+1;
					if(mm[p][i]==mm[p][i+1]) dp[now][p][q][i]=dp[now][p][q][i+1];
					else dp[now][p][q][i]=i+1;
				}
				else
				{
					if(mm[q-1][i]==mm[q][i]) dp[now][p][q][i]=min(dp[now][p][q-1][i],dp[now][q][q][i]);
					else dp[now][p][q][i]=i;
				}
			}
		}
	}
	for(ans=0;;ans++)
	{
		if(dp[now][1][m][1]==n+1)
		{
			cout<<ans;
			return 0;
		}
		swap(now,cur);
		for(p=1;p<=m;p++)
		{
			for(q=p;q<=m;q++)
			{
				for(i=1;i<=n;i++)
				{
					if(dp[cur][p][q][i]==n+1) dp[now][p][q][i]=n+1;
					else dp[now][p][q][i]=dp[cur][p][q][dp[cur][p][q][i]];
					for(l=p,r=q;l<r;)
					{
						mid=((l+r)>>1);
						Max(dp[now][p][q][i],min(dp[cur][p][mid][i],dp[cur][mid+1][q][i]));
						if(dp[cur][p][mid][i]>dp[cur][mid+1][q][i]) l=mid+1;
						else r=mid;
					}
				}
			}
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章