懸線法的模板題,下面主要講懸線法:
懸線法思路:懸線的定義,就是一條豎線,這條豎線要滿足上端點在整個矩形上邊界或者是乙個障礙點。然後以這條懸線進行左右移動,直到移至障礙點或者是矩陣邊界,進而確定這條懸線所在的極大矩陣。
具體方法:
先預處理:
用陣列l,r記錄某點向左和向右能到達的最遠點的縱座標。 用陣列up記錄某點向上能到達的最遠距離。
//處理l
for (int i=1; i<=n; i++)
for (int j=2; j<=m; j++)
if (map[i][j]==1 && map[i][j-1]==1) l[i][j]=l[i][j-1];
//處理r
for (int i=1; i<=n; i++)
for (int j=m-1; j>=1; j--)
if (map[i][j]==1 && map[i][j+1]==1) r[i][j]=r[i][j+1];
對每乙個點找最大面積:
for (int i=1; i<=n; i++)
ans=max(ans, (r[i][j]-l[i][j]+1)*up[i][j]);
}}
最後是ac**:
#includeusing namespace std;
const int n=1e3+10;
int n, m, ans, map[n][n];
int l[n][n], r[n][n], up[n][n];
int min(int x, int y)
int max(int x, int y)
int main()
}for (int i=1; i<=n; i++)
for (int j=2; j<=m; j++)
if (map[i][j]==1 && map[i][j-1]==1) l[i][j]=l[i][j-1];
for (int i=1; i<=n; i++)
for (int j=m-1; j>=1; j--)
if (map[i][j]==1 && map[i][j+1]==1) r[i][j]=r[i][j+1];
for (int i=1; i<=n; i++)
ans=max(ans, (r[i][j]-l[i][j]+1)*up[i][j]);}}
cout << ans*3;
return 0;
}
總結:其實懸線法還是比較基礎的,理解起來也很好理解。
補充一道懸線法的題目:
這是**:
#includeusing namespace std;
const int n=2e3+10;
int n, m, ans1, ans2, map[n][n];
int l[n][n], r[n][n], up[n][n];
int main()
} for (int i=1; i<=n; i++)
for (int j=2; j<=m; j++)
if (map[i][j]!=map[i][j-1]) l[i][j]=l[i][j-1];
for (int i=1; i<=n; i++)
for (int j=m-1; j>=1; j--)
if (map[i][j]!=map[i][j+1]) r[i][j]=r[i][j+1];
for (int i=1; i<=n; i++)
}ans1=max(ans1, min(r[i][j]-l[i][j]+1, up[i][j])*min(r[i][j]-l[i][j]+1, up[i][j]));
ans2=max(ans2, (r[i][j]-l[i][j]+1)*up[i][j]);
} }cout << ans1 << endl << ans2;
return 0;
}
只需要稍作修改便能夠a掉。 懸線法 棋盤製作
description 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟...
懸線法DP總結
求滿足某種條件 如01交替 的最大矩形 正方形 先預處理出 ml i j mr i j mt i j 分別表示當前位置 i,j 能向左擴充套件到的最左邊的編號 能向右擴充套件到的最右邊的編號 能向上擴充套件到的最大高度。然後在做 dp 時,除第一行,每行根據上一行的狀態更新當前狀態,逐行掃一遍。複雜...
ACM 懸線法總結
一般分為兩種做法 有乙個n m的矩陣,初始為白色,裡面有s個黑色格仔,現在問能在矩陣裡面找到的最大不包含 黑色格仔的子矩陣 正方形 n,m 1000,s n m 例題 p2701 usaco5.3 巨大的牛棚big barn 農夫約翰想要在他的正方形農場上建造一座正方形大牛棚。他討厭在他的農場中砍樹...