傳送門
dp找給定區域內最大符合條件的矩形/正方形。這裡有一種新的方法———懸線法。
懸線的定義:每個點(i,j),都對應一條懸線,當前點是懸線的下端,懸線的上端為乙個障礙點或者矩形的上邊界。
所以乙個符合條件的矩形,我們只要使用懸線法計算出這條懸線移動到不合法位置時的邊界即可。
(注意left和right似乎在iostream庫中是保留字)
用lef[i][j]表示從點(i,j)引出的懸線能拓展到的最左邊的位置,righ[i][j]表示從點(i,j)引出的懸線能拓展到最右邊的位置。up[i][j]表示這條懸線能向上拓展的最大長度。
這樣我們可以先預處理出每條懸線的lef,righ,只要左右兩格不同就可以進行轉移。
之後我們就得到遞推式:
left[i][j]=max(left[i][j],left[i-1][j];
right[i][j]=min(right[i][j],right[i-1][j];
注意這裡要考慮上一行的情況,是因為up的原因。
之後從上向下dp,每次處理一下當前的最大合法矩形即可。
#include#include#include
//#include
#include#include
#include
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using
namespace
std;
typedef
long
long
ll;const
int m = 50005
;int
read()
while(ch >= '
0' && ch <= '9'
)
return ans *op;
}int n,m,g[2005][2005],up[2005][2005],lef[2005][2005],right[2005][2005
];int
ans1,ans2;
intmain()
int lena = right[i][j] - lef[i][j] + 1
;
int lenb =min(lena,up[i][j]);
ans1 = max(ans1,lenb*lenb);
ans2 = max(ans2,lena*up[i][j]);
}printf(
"%d\n%d\n
",ans1,ans2);
return0;
}
ZJOI2007 棋盤製作
題目描述 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟他的好朋友小w...
ZJOI2007 棋盤製作
十二年前的zjoi我現在還切不過我是不是可以退役了 傳送門 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 times 88 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作...
棋盤製作 ZJOI2007
題目傳送門 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟他的好朋友小...