H - Maximal submatrix HDU - 6957
生活随笔
收集整理的這篇文章主要介紹了
H - Maximal submatrix HDU - 6957
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
H - Maximal submatrix HDU - 6957
題意:
給定一個(gè)n行m列的矩陣,求每列上面積不減的最大子矩陣
對(duì)于每個(gè)測(cè)試用例,打印一個(gè)表示最大子矩陣的整數(shù)
題解:
要求求一個(gè)最大面積的滿足每列非遞減的矩陣,這怎么想?
我們可以轉(zhuǎn)化成01矩陣,每一個(gè)位置1表示該位置比上面一位大,然后求最大的01矩陣就可以了,單調(diào)棧做法時(shí)注意0的話可以作為矩陣的開(kāi)始,詳細(xì)看看代碼
代碼:
單調(diào)棧做法
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); typedef long long ll; using namespace std; //Fe~Jozky const ll INF=0x3f3f3f3f; inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } int n,m; const int maxn=2e3+9; int a[maxn][maxn]; int h[maxn][maxn]; int w[maxn][maxn]; int st[maxn],top; int ans=0; void precal(){memset(w,0,sizeof(w));for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(h[i][j]==0)w[i][j]=1;else w[i][j]=w[i-1][j]+1;}w[i][m+1]=-1; } } void cal(){for(int i=1;i<=n;i++){top==0;for(int j=1;j<=m+1;j++){if(top==0||w[i][j]>=w[i][st[top]]){st[++top]=j;}else {int id;while(top!=0&&w[i][j]<w[i][st[top]]){id=st[top];top--;ans=max(ans,(j-id)*w[i][id]);}st[++top]=id;w[i][id]=w[i][j];}}} } void solve(){n=read();m=read();for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){a[i][j]=read();}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]>=a[i-1][j])h[i][j]=1;else h[i][j]=0;}}precal();cal(); cout<<ans<<endl; } int main() {#ifdef ONLINE_JUDGE#elsefreopen("1.in","r",stdin);#endifint t;t=read();while(t--){ans=0;solve();}fclose(stdin);return 0; }縱向的懸線法
#include <iostream> #include <cstring> #define FAST ios::sync_with_stdio(false);cin.tie(0),cout.tie(0) #define endl '\n' #define debug(x) cout << #x << " = " << (x) << endl #define mem(a,b) memset(a,b,sizeof(a)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define rep(i,a,n) for(int i=a;i<=n;++i) #define per(i,n,a) for(int i=n;i>=a;--i)using namespace std;const int maxn = 2e3+5;int n, m; short a[maxn][maxn]; bool b[maxn][maxn]; short up[maxn][maxn], down[maxn][maxn], len[maxn][maxn];void tran() {mem(b, 0);rep(i, 1, n) {rep(j, 1, m) {if (i == 1) continue;else if (a[i][j] >= a[i-1][j]) b[i][j] = 1;}} }void init() {rep(i, 1, n) {rep(j, 1, m) {up[i][j] = i;down[i][j] = i;len[i][j] = 1;}} }int main() {FAST;int t; cin >> t;while (t--) {cin >> n >> m;rep(i, 1, n) {rep(j, 1, m) {cin >> a[i][j];}}tran();init();rep(j, 1, m) {rep(i, 2, n) {if (b[i][j]) up[i][j] = up[i-1][j];}per(i, n-1, 1) {if (b[i+1][j]) down[i][j] = down[i+1][j];}}int ans = m;rep(j, 1, m) {rep(i, 1, n) {if (b[i][j-1]) {len[i][j] = len[i][j-1] + 1;up[i][j] = max(up[i][j], up[i][j-1]);down[i][j] = min(down[i][j], down[i][j-1]);}int llen = down[i][j] - up[i][j] + 1;ans = max(ans, llen * len[i][j]);}}cout << ans << endl;}return 0; }另一種懸線法
寫(xiě)法就是:對(duì)于每一行的最大范圍就是兩側(cè)0之間,我們?cè)O(shè)高度一開(kāi)始為0,是因?yàn)槊恳粋€(gè)矩陣第一行是可以有0的,但是之后不可以,所以我們最后得到的高度還要算上第一行。相當(dāng)于我們刨去第一行考慮01矩陣,最后再算上第一行
比如:01矩陣:
我們先不考慮第一行,然后考慮后兩行的左右寬度和高,左=2,右為4,高為2,那么答案就是(4-2+1)*(2+1)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int maxn=2e3+10; int t,n,m; int l[maxn][maxn]; int le[maxn][maxn]; int r[maxn][maxn]; int h[maxn][maxn]; int main() {cin>>t;while(t--){cin>>n>>m;memset(le,0,sizeof(le));for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){le[0][j]=0;scanf("%d",&l[i][j]);if(i!=1)if(l[i][j]>=l[i-1][j]){le[i][j]=1;}//else le[i][j]=1;}}memset(l,0,sizeof(l));memset(h,0,sizeof(h));memset(r,0,sizeof(r));int ans=m;int L=1e9,R=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(le[i][j]==1){L=min (L,j);}else L=1e9;l[i][j]=L;//如果當(dāng)前點(diǎn)為0,左端點(diǎn)取正無(wú)窮 }for(int j=m;j>=1;j--){if(le[i][j]==1){R=max(R,j);}else R=0;r[i][j]=R;//如果當(dāng)前端點(diǎn)為0,右端點(diǎn)取無(wú)窮小 }for(int j=1;j<=m;j++){if(le[i-1][j]==1){h[i][j]=h[i-1][j]+1;l[i][j]=max(l[i-1][j],l[i][j]);r[i][j]=min(r[i-1][j],r[i][j]);}else h[i][j]=1;if(le[i][j]==1){ans=max(ans,(r[i][j]-l[i][j]+1)*(h[i][j]+1));}}} cout<<ans<<endl;}return 0; }總結(jié)
以上是生活随笔為你收集整理的H - Maximal submatrix HDU - 6957的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Minimum spanning tre
- 下一篇: 纤怎么读 纤的拼音是什么