题解P1169 [ZJOI2007]棋盘制作

题目:P1169 [ZJOI2007]棋盘制作 

方法:悬线法

用途:解决矩形内满足要求的最优(最大)矩形的问题

实现方法:用一条线(横竖都行)不断向左右移动知道不满足约束或者到了边界为止

本题用l[i][j]表示(i,j)可以扩展的最左边的位置,r[i][j]表示可以扩展的最右边的位置,len[i][j]表示向上扩展的最长长度。

 1 #include<stdio.h>
 2 #define it register int
 3 #define il inline
 4 const int N=2005;
 5 int l[N][N],r[N][N],a[N][N],len[N][N],n,m,ans1,ans2;
 6 il int Min(it p,it q){
 7     return p<q?p:q;
 8 }
 9 il int Max(it p,it q){
10     return p>q?p:q;
11 }
12 il void fr(int &num){
13     num=0;char c=getchar();int p=1;
14     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
15     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
16     num*=p;
17 }   
18 int main(){
19     fr(n),fr(m);
20     for(it i=1;i<=n;++i)
21         for(it j=1;j<=m;++j)
22             fr(a[i][j]),l[i][j]=r[i][j]=j,len[i][j]=1; 
23     for(it i=1;i<=n;++i)
24         for(it j=2;j<=m;++j)
25             if(a[i][j]!=a[i][j-1]) l[i][j]=l[i][j-1];
26     for(it i=1;i<=n;++i)
27         for(it j=m-1;j;--j)
28             if(a[i][j]!=a[i][j+1]) r[i][j]=r[i][j+1]; 
29     //记录(i,j)可以向左右扩展的位置 
30     for(it i=1,l1,r1;i<=n;++i)
31         for(it j=1;j<=m;++j){
32             if(i>1&&a[i][j]!=a[i-1][j]) l[i][j]=Max(l[i][j],l[i-1][j]),r[i][j]=Min(r[i][j],r[i-1][j]),len[i][j]=len[i-1][j]+1; //每次向上一层更新 
33             l1=r[i][j]-l[i][j]+1,r1=Min(l1,len[i][j]),ans1=Max(ans1,r1*r1),ans2=Max(ans2,len[i][j]*l1); //更新答案 
34         } 
35     printf("%d
%d
",ans1,ans2);
36     return 0;
37 }
View Code
原文地址:https://www.cnblogs.com/Kylin-xy/p/11775995.html