洛谷 P1169||bzoj1057 [ZJOI2007]棋盘制作

洛谷P1169

bzoj1057

这个题目跟最大全0子矩阵是类似的。正方形的话,只要把任意极大子正方形(”极大“定义见后面的”论文“)当成把某个极大子矩形去掉一块变成正方形即可,容易解决。

解法1:看论文里面的“算法2“(那个是最大全0子矩阵方法,改一下就可以用在此题)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pii;
13 int n,m;
14 int a[2010][2010];
15 int lp[2010][2010],rp[2010][2010];
16 int lx[2010][2010],rx[2010][2010];
17 int hei[2010][2010];
18 int an1,an2;
19 int calc(int x,int y)
20 {
21     return min(x,y)*min(x,y);
22 }
23 int main()
24 {
25     int i,j;
26     scanf("%d%d",&n,&m);
27     for(i=1;i<=n;++i)
28     {
29         for(j=1;j<=m;++j)
30         {
31             scanf("%d",&a[i][j]);
32         }
33     }
34     for(i=1;i<=n;++i)
35     {
36         lx[i][1]=1;
37         for(j=2;j<=m;++j)
38             lx[i][j]=(a[i][j]==a[i][j-1])?j:lx[i][j-1];
39         rx[i][m]=m;
40         for(j=m-1;j>=1;--j)
41             rx[i][j]=(a[i][j]==a[i][j+1])?j:rx[i][j+1];
42     }
43     for(i=1;i<=n;++i)
44     {
45         for(j=1;j<=m;++j)
46         {
47             if(i!=1&&a[i][j]!=a[i-1][j])
48             {
49                 hei[i][j]=hei[i-1][j]+1;
50                 lp[i][j]=max(lp[i-1][j],lx[i][j]);
51                 rp[i][j]=min(rp[i-1][j],rx[i][j]);
52             }
53             else
54             {
55                 hei[i][j]=1;
56                 lp[i][j]=lx[i][j];
57                 rp[i][j]=rx[i][j];
58             }
59             //printf("1t%d %d %d %d %d\n",i,j,hei[i][j],lp[i][j],rp[i][j]);
60             an1=max(an1,hei[i][j]*(rp[i][j]-lp[i][j]+1));
61             an2=max(an2,calc(hei[i][j],rp[i][j]-lp[i][j]+1));
62         }
63     }
64     printf("%d\n",an2);
65     printf("%d\n",an1);
66     return 0;
67 }
View Code

解法2:

其实最大全0子矩阵还有一种做法:

枚举每一行作为子矩阵的下底部,求出每一列向上最多扩展几行,然后直接用lightoj1083的做法求解此时的最大子矩阵,取所有方案最大值即可

改一下也可以用在此题

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pii;
13 int st[2010],r[2010],l[2010],len;
14 int an1,an2;
15 int n,m;
16 int calc(int x,int y)
17 {
18     return min(x,y)*min(x,y);
19 }
20 void solve(int *d,int m)
21 {
22     int i;
23     len=0;
24     for(i=1;i<=m;++i)
25     {
26         while(len>0&&d[st[len]]>=d[i])    r[st[len--]]=i-1;
27         l[i]=st[len];
28         st[++len]=i;
29     }
30     while(len>0)    r[st[len--]]=m;
31     for(i=1;i<=m;++i)
32     {
33         an1=max(an1,d[i]*(r[i]-l[i]));
34         an2=max(an2,calc(d[i],r[i]-l[i]));
35     }
36 }
37 int a[2010][2010],hei[2010][2010];
38 int main()
39 {
40     int i,j,k;
41     scanf("%d%d",&n,&m);
42     for(i=1;i<=n;++i)
43     {
44         for(j=1;j<=m;++j)
45         {
46             scanf("%d",&a[i][j]);
47             hei[i][j]=(i==1||a[i][j]==a[i-1][j])?1:hei[i-1][j]+1;
48         }
49     }
50     for(i=1;i<=n;++i)
51     {
52         for(j=1;j<=m;j=k+1)
53         {
54             k=j;
55             while(k+1<=m&&a[i][k+1]!=a[i][k])    ++k;
56             //printf("1t%d %d %d\n",i,j,k);
57             solve(hei[i]+j-1,k-j+1);
58         }
59     }
60     printf("%d\n",an2);
61     printf("%d\n",an1);
62     return 0;
63 }
View Code

 

posted @ 2018-10-25 22:07  hehe_54321  阅读(150)  评论(0编辑  收藏  举报
AmazingCounters.com