2019年暑假多校牛客第八場A All-one Matrices【01矩陣-極大全1矩陣】

題目鏈接:https://ac.nowcoder.com/acm/contest/888/A
題目大意:給定nmn*m的01矩陣,求該矩陣中極大全1矩陣的數目。
思路:
我們在處理極大全1矩陣的過程中,關鍵在於判斷當前所求矩陣是否會被包含在後續求出來的矩陣中。那麼要在知道會不會被包含在下一行的矩陣中,對於行方向:只要知道當前這一行,這個矩陣的對應的1位置,如果下一行中相應位置也全爲1,那麼一定會被包含,如果下一行中對應位置中有一個位置爲0,那麼說明這個矩陣不會被包含在下一行的最大矩陣中,當前行爲該矩陣的最後一行。對於列方向:可以先預處理一下每列的前綴和,然後對每一行用單調棧維護前綴和最大值即可。
AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=3010;
int h[maxn][maxn];
int n,m;
char mp[maxn][maxn];
struct node
{
    int pos;//pos存的是單調棧中對應點的列
    int value;//value存的是列的前綴和(h[][])
};
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>mp[i][j];
            h[i][j]=0;
        }
        h[i][m+1]=0;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(mp[i][j]=='1'){
                h[i][j]=h[i-1][j]+1;//求每列的前綴和
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        int tmpos=-1,tmp=-1;
        stack<node>stk;//單調棧維護
        for(int j=1;j<=m+1;j++){
            tmpos=j;
            while(!stk.empty()&&stk.top().value>h[i][j]){
                if(stk.top().pos<=tmp){
                    ans++;
                }
                tmpos=stk.top().pos;//tmpos記錄的是單調棧中不合法的最後一個節點的位置
                stk.pop();
            }
            if(h[i+1][j]==0){//當前列的下一行爲0,說明當前列所在的矩陣不能擴展到下一行
                tmp=j;//tmp記錄當前列
            }
            if(h[i][j]&&(stk.empty()||stk.top().value<h[i][j])){
                node t;
                t.pos=tmpos,t.value=h[i][j];
                stk.push(t);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章