APIO2009 採油區域(列舉 遞推)

2021-07-02 05:39:53 字數 1588 閱讀 9574

切分矩形,遞推輔助:

觀察分割方案,可(很)以(難)發(想)現(到),將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...