懸線法簡單題應用

2021-09-10 23:19:15 字數 3378 閱讀 8843

p1169 [zjoi2007]棋盤製作

題意:給出乙個01矩陣,求最大01相間的正方形和長方形面積

用三個陣列left[i][j],right[i][j],up[i][j]分別表示(i,j)這個點符合條件的最左邊界、最右邊界,和最大高度

左右邊界可以預處理:

for 行:

for 右->左:

if 當前位置(i,j)和右邊一格(i,j+1)的值不同(需要01相間):

right[i][j] = right[i][j+1]

相似處理左邊界,這樣每個點都知道了它的左右邊界。

然後從上到下,一行一行列舉每個點,如果當前點和上面的那個點是不同的,就記錄一下公共的左右邊界,更新當前點的高度

up[i][j] = up[i-1][j] + 1

這時可以計算出新增了這行後上面的合法矩形擴張後的面積,更新答案

#includeusing namespace std;

const int n=2005;

int mp[n][n];

int le[n][n],ri[n][n],up[n][n];

int main()

}for(int i=1;i<=n;i++)//處理右邊界

for(int j=m-1;j>=1;j--)

if(mp[i][j]!=mp[i][j+1])

ri[i][j]=ri[i][j+1];

for(int i=1;i<=n;i++)//處理左邊界

for(int j=2;j<=m;j++)

if(mp[i][j]!=mp[i][j-1])

le[i][j]=le[i][j-1];

int ans1=0,ans2=0;

for(int i=1;i1&&mp[i][j]!=mp[i-1][j])//不是第一行,且這個點和上面的點不同

int w=ri[i][j]-le[i][j]+1;//寬

int x=min(w,up[i][j]);//正方形邊長肯定是矩形中短的那條

ans1=max(ans1,x*x);//更新正方形的答案

ans2=max(ans2,w*up[i][j]);//更新長方形的答案}}

printf("%d\n%d\n",ans1,ans2);

return 0;

}

p4147玉蟾宮

題意:給出乙個由『f』和『r』構成的矩陣,求出最大的僅含有『f』的矩陣面積*3

跟上面那題基本相同,判斷條件改下即可

mp[i][j] == 相鄰格仔 && mp[i][j] == 'f'

#includeusing namespace std;

const int n=1005;

char mp[n][n];

int le[n][n],ri[n][n],up[n][n];

char s[2];

int main()

getchar();

}for(int i=1;i<=n;i++)

for(int j=m-1;j>=1;j--)

if(mp[i][j]==mp[i][j+1]&&mp[i][j]=='f')

ri[i][j]=ri[i][j+1];

for(int i=1;i<=n;i++)

for(int j=2;j<=m;j++)

if(mp[i][j]==mp[i][j-1]&&mp[i][j]=='f')

le[i][j]=le[i][j-1];

int ans=0;

for(int i=1;i<=n;i++)

int w=ri[i][j]-le[i][j]+1;

ans=max(ans,w*up[i][j]);}}

printf("%d\n",3*ans);

return 0;

}

p2701[usaco5.3]巨大的牛棚big barn

題意:求最大的僅含有空地的正方形邊長

幾乎是一樣的題目

#includeusing namespace std;

const int n=1005;

int mp[n][n];

int le[n][n],ri[n][n],up[n][n];

int main()

for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

for(int i=1;i<=n;i++)

for(int j=n-1;j>=1;j--)

if(mp[i][j]==mp[i][j+1]&&mp[i][j]==0)

ri[i][j]=ri[i][j+1];

for(int i=1;i<=n;i++)

for(int j=2;j<=n;j++)

if(mp[i][j]==mp[i][j-1]&&mp[i][j]==0)

le[i][j]=le[i][j-1];

int ans=0;

for(int i=1;i<=n;i++)

int w=ri[i][j]-le[i][j]+1;

int x=min(w,up[i][j]);

ans=max(ans,x);}}

printf("%d\n",ans);

return 0;

}

p1387最大正方形

題意:求最大僅含有1的正方形

#includeusing namespace std;

const int n=1005;

int mp[n][n];

int le[n][n],ri[n][n],up[n][n];

int main()

for(int i=1;i<=n;i++)

for(int j=m-1;j>=1;j--)

if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)

ri[i][j]=ri[i][j+1];

for(int i=1;i<=n;i++)

for(int j=2;j<=m;j++)

if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)

le[i][j]=le[i][j-1];

int ans=0;

for(int i=1;i<=n;i++)

int w=ri[i][j]-le[i][j]+1;

int x=min(w,up[i][j]);

ans=max(ans,x);}}

printf("%d\n",ans);

return 0;

}

關於懸線法

懸線法的模板題,下面主要講懸線法 懸線法思路 懸線的定義,就是一條豎線,這條豎線要滿足上端點在整個矩形上邊界或者是乙個障礙點。然後以這條懸線進行左右移動,直到移至障礙點或者是矩陣邊界,進而確定這條懸線所在的極大矩陣。具體方法 先預處理 用陣列l,r記錄某點向左和向右能到達的最遠點的縱座標。用陣列up...

懸線法 棋盤製作

description 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟...

懸線法DP總結

求滿足某種條件 如01交替 的最大矩形 正方形 先預處理出 ml i j mr i j mt i j 分別表示當前位置 i,j 能向左擴充套件到的最左邊的編號 能向右擴充套件到的最右邊的編號 能向上擴充套件到的最大高度。然後在做 dp 時,除第一行,每行根據上一行的狀態更新當前狀態,逐行掃一遍。複雜...