切分矩形,遞推輔助:
觀察分割方案,可(很)以(難)發(想)現(到),將m*n的格仔切兩次,成為三個矩形區域,三個k*k的塊一定分別包含於其中乙個區域
題目就轉化為:求指定矩形區域中的最大的 k*k塊的元素和
考慮用遞推來預處理,優化列舉效率
預處理:
二維字首和
s[i][j]:右下角為(i,j)的k*k塊的元素和
ul,ur,dl,dr[i][j]:從 左上角、右上角、左下角、右下角 到(i,j)構成的矩形中,k*k塊的元素和的最大值
l[i],h[i]:sigma(s[i][j])、sigma(s[j][i]),j屬於[1,m或n]
列舉切分的線:
一橫一豎:分成的三個區域可以直接用ul,ur,dl,dr實現o(1)查詢最大值 複雜度:o(m*n)
兩橫/兩豎:只列舉一條線即可,因為可以規定另一條線與其間距為k,那麼分成的三個區域中:邊上的用ul,ur,dl查詢,中間的用l,h查詢 複雜度:o(m+n)
記錄以上所有情況中的最大值即可
注意:觀察方案尋找規律,遞推注意順序
#include#includeint sum[1505][1505],s[1505][1505],ul[1505][1505],ur[1505][1505],dl[1505][1505],dr[1505][1505],l[1505],h[1505];//記憶體限制:不能定義成3000^2
int max(int a,int b)
int main()
for(i=k;i<=m;i++)
for(j=k;j<=n;j++)
ul[i][j]=max(max(ul[i-1][j],ul[i][j-1]),s[i][j]);
for(i=k;i<=m;i++)
for(j=n-k+1;j>=1;j--)//注意遞推的順序!!!
ur[i][j]=max(max(ur[i-1][j],ur[i][j+1]),s[i][j+k-1]);
for(i=m-k+1;i>=1;i--)
for(j=k;j<=n;j++)
dl[i][j]=max(max(dl[i][j-1],dl[i+1][j]),s[i+k-1][j]);
for(i=m-k+1;i>=1;i--)
for(j=n-k+1;j>=1;j--)
dr[i][j]=max(max(dr[i+1][j],dr[i][j+1]),s[i+k-1][j+k-1]);
for(i=k;i<=m;i++)
for(j=k;j<=n;j++)
for(i=k;i<=m-k;i++)//一橫一豎
for(j=k;j<=n-k;j++)
for(i=2*k;i<=m-k;i++)//兩條橫線,列舉下面一條
ans=max(ans,ul[i-k][n]+l[i]+dl[i+1][n]);
for(i=2*k;i<=n-k;i++)//兩條豎線,列舉右面一條
ans=max(ans,ul[m][i-k]+h[i]+ur[m][i+1]);
printf("%d",ans);
return 0;
}
洛谷P3625 APIO2009 採油區域
portal 給出乙個 n times m n,m leq1500 的矩陣,從中選出 3 個互不相交的 k times k 方陣,使得被選出的數的和最大。奇怪做法.三個矩形分別在三個部分中,把矩形劃分成三部分只有這六種。首先搞出 s i j 表示以 i,j 為右下角的 k times k 方陣的和,...
省選專練APIO2009Oil採油區域
神仙題難點在於 實現 這狗日的題。首先暴力是這樣的 列舉三個座標 這是n 6做法,沒什麼卵用 但是我們發現把一張圖分割成3塊那麼可以做 但是問題是這是情況多多的 所以成了碼農題 includeusing namespace std const int n 1801 int sum n n int a...
APIO2009 搶掠計畫
description siruseri城中的道路都是單向的。不同的道路由路口連線。按照法律的規定,在每個路口都設立了乙個siruseri銀行的atm取款機。令人奇怪的是,siruseri的酒吧也都設在路口,雖然並不是每個路口都設有酒吧。banditji計畫實施siruseri有史以來最驚天動地的a...