日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

H - Maximal submatrix HDU - 6957

發布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 H - Maximal submatrix HDU - 6957 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

H - Maximal submatrix HDU - 6957

題意:

給定一個n行m列的矩陣,求每列上面積不減的最大子矩陣

對于每個測試用例,打印一個表示最大子矩陣的整數

題解:

要求求一個最大面積的滿足每列非遞減的矩陣,這怎么想?
我們可以轉化成01矩陣,每一個位置1表示該位置比上面一位大,然后求最大的01矩陣就可以了,單調棧做法時注意0的話可以作為矩陣的開始,詳細看看代碼

代碼:

單調棧做法

#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; }

另一種懸線法

寫法就是:對于每一行的最大范圍就是兩側0之間,我們設高度一開始為0,是因為每一個矩陣第一行是可以有0的,但是之后不可以,所以我們最后得到的高度還要算上第一行。相當于我們刨去第一行考慮01矩陣,最后再算上第一行
比如:01矩陣:

01011 01110 11111

我們先不考慮第一行,然后考慮后兩行的左右寬度和高,左=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;//如果當前點為0,左端點取正無窮 }for(int j=m;j>=1;j--){if(le[i][j]==1){R=max(R,j);}else R=0;r[i][j]=R;//如果當前端點為0,右端點取無窮小 }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; }

總結

以上是生活随笔為你收集整理的H - Maximal submatrix HDU - 6957的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。