採油區域-APIO 2009
阿新 • • 發佈:2018-12-27
演算法訓練 採油區域
時間限制:2.0s 記憶體限制:512.0MB
採油區域 Siruseri政府決定將石油資源豐富的Navalur省的土地拍賣給私人承包商以建立油井。被拍賣的整塊土地為一個矩形區域,被劃分為M×N個小塊。
Siruseri地質調查局有關於Navalur土地石油儲量的估測資料。這些資料表示為M×N個非負整數,即對每一小塊土地石油儲量的估計值。
為了避免出現壟斷,政府規定每一個承包商只能承包一個由K×K塊相連的土地構成的正方形區域。
AoE石油聯合公司由三個承包商組成,他們想選擇三塊互不相交的K×K的區域使得總的收益最大。
例如,假設石油儲量的估計值如下:
如果K = 2, AoE公司可以承包的區域的石油儲量總和為100, 如果K = 3, AoE公司可以承包的區域的石油儲量總和為208。
AoE公司僱傭你來寫一個程式,幫助計算出他們可以承包的區域的石油儲量之和的最大值。 輸入格式 輸入第一行包含三個整數M, N, K,其中M和N是矩形區域的行數和列數,K是每一個承包商承包的正方形的大小(邊長的塊數)。接下來M行,每行有N個非負整數表示這一行每一小塊土地的石油儲量的估計值。 輸出格式 輸出只包含一個整數,表示AoE公司可以承包的區域的石油儲量之和的最大值。 資料規模和約定 資料保證K≤M且K≤N並且至少有三個K×K的互不相交的正方形區域。其中30%的輸入資料,M, N≤ 12。所有的輸入資料, M, N≤ 1500。每一小塊土地的石油儲量的估計值是非負整數且≤ 500。 樣例輸入 9 9 3
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 1 1 1 8 8 8 1 1
1 1 1 1 1 1 8 8 8
1 1 1 1 1 1 9 9 9
1 1 1 1 1 1 9 9 9 樣例輸出 208
Siruseri地質調查局有關於Navalur土地石油儲量的估測資料。這些資料表示為M×N個非負整數,即對每一小塊土地石油儲量的估計值。
為了避免出現壟斷,政府規定每一個承包商只能承包一個由K×K塊相連的土地構成的正方形區域。
AoE石油聯合公司由三個承包商組成,他們想選擇三塊互不相交的K×K的區域使得總的收益最大。
例如,假設石油儲量的估計值如下:
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
8 |
8 |
8 |
8 |
8 |
1 |
1 |
1 |
1 |
8 |
8 |
8 |
8 |
8 |
1 |
1 |
1 |
1 |
8 |
8 |
8 |
8 |
8 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
8 |
8 |
8 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
8 |
8 |
8 |
1 |
1 |
1 |
1 |
1 |
1 |
9 |
9 |
9 |
1 |
1 |
1 |
1 |
1 |
1 |
9 |
9 |
9 |
如果K = 2, AoE公司可以承包的區域的石油儲量總和為100, 如果K = 3, AoE公司可以承包的區域的石油儲量總和為208。
AoE公司僱傭你來寫一個程式,幫助計算出他們可以承包的區域的石油儲量之和的最大值。 輸入格式 輸入第一行包含三個整數M, N, K,其中M和N是矩形區域的行數和列數,K是每一個承包商承包的正方形的大小(邊長的塊數)。接下來M行,每行有N個非負整數表示這一行每一小塊土地的石油儲量的估計值。 輸出格式 輸出只包含一個整數,表示AoE公司可以承包的區域的石油儲量之和的最大值。 資料規模和約定 資料保證K≤M且K≤N並且至少有三個K×K的互不相交的正方形區域。其中30%的輸入資料,M, N≤ 12。所有的輸入資料, M, N≤ 1500。每一小塊土地的石油儲量的估計值是非負整數且≤ 500。 樣例輸入 9 9 3
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 8 8 8 8 8 1 1 1
1 1 1 1 8 8 8 1 1
1 1 1 1 1 1 8 8 8
1 1 1 1 1 1 9 9 9
1 1 1 1 1 1 9 9 9 樣例輸出 208
因為只有三塊,所以對於整體的劃分可分為六種情況:
||| -| = |- T 丨
於是可以進行六次遍歷
可以先定義
s[i][j]代表1..i行1..j列數字之和。
然後處理出以(i,j)為右下角的k*k的矩陣元素之和。
然後分別處理出以(i,j)為左上角,左下角,右上角,右下角的最大矩陣中最大的k*k的值。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #define gmax(a,b) ((a)>(b)?(a):(b)) #define fill(a,b) memset(a,b,sizeof(a)) #define MAXN 2000 #define MAXM 2000 using namespace std; int n, m, k; int a[MAXN][MAXM]; int s[MAXN][MAXM]; int ak[MAXN][MAXM]; int lu[MAXN][MAXM], ru[MAXN][MAXM], ld[MAXN][MAXM], rd[MAXN][MAXM]; int ans; int main(){ int i, j; scanf("%d %d %d", &n, &m, &k); for (i=1; i<n+1; i++){ for (j=1; j<m+1; j++){ scanf("%d", &a[i][j]); } } fill(s, 0); for (i=1; i<n+1; i++){ for (j=1; j<m+1; j++){ s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j]; } } fill(ak, 0); for (i=k; i<n+1; i++){ for (j=k; j<m+1; j++){ ak[i][j] = s[i][j] - s[i - k][j] - s[i][j - k] + s[i - k][j - k]; } } fill(lu, 0); for (i=k; i<n+1; i++){ for (j=k; j<m+1; j++){ lu[i][j] = ak[i][j]; lu[i][j] = gmax(lu[i][j], lu[i - 1][j]); lu[i][j] = gmax(lu[i][j], lu[i][j - 1]); } } fill(ru, 0); for (i=k; i<n+1; i++){ for (j=m-k+1; j; j--){ ru[i][j] = ak[i][j + k - 1]; ru[i][j] = gmax(ru[i][j], ru[i - 1][j]); ru[i][j] = gmax(ru[i][j], ru[i][j + 1]); } } fill(ld, 0); for (i=n-k+1; i; i--){ for (j=k; j<m+1; j++){ ld[i][j] = ak[i + k - 1][j]; ld[i][j] = gmax(ld[i][j], ld[i + 1][j]); ld[i][j] = gmax(ld[i][j], ld[i][j - 1]); } } fill(rd, 0); for (i=n-k+1; i; i--){ for (j=m-k+1; j; j--){ rd[i][j] = ak[i + k - 1][j + k - 1]; rd[i][j] = gmax(rd[i][j], rd[i + 1][j]); rd[i][j] = gmax(rd[i][j], rd[i][j + 1]); } } ans = 0; for (j=k; j+(k<<1)<m+1; j++){ for (i=k; i<n+1; i++){ int t = lu[n][j] + ak[i][j + k] + ru[n][j + k + 1]; ans = gmax(ans, t); } } for (i=k; i+(k<<1)<n+1; i++){ for (j=k; j<m+1; j++){ int t = lu[i][m] + ak[i + k][j] + ld[i + k + 1][m]; ans = gmax(ans, t); } } for (j=k; j+k<m+1; j++){ for (i=k; i+k<n+1; i++){ int t = lu[n][j] + ru[i][j + 1] + rd[i + 1][j + 1]; ans = gmax(ans, t); } } for (j=k; j+k<m+1; j++){ for (i=k; i+k<n+1; i++){ int t = lu[i][j] + ld[i + 1][j] + rd[1][j + 1]; ans = gmax(ans, t); } } for (i=k; i+k<n+1; i++){ for (j=k; j+k<m+1; j++){ int t = lu[i][n] + ld[i + 1][j] + rd[i + 1][j + 1]; ans = gmax(ans, t); } } for (i=k; i+k<n+1; i++){ for (j=k; j+k<m+1; j++){ int t = lu[i][j] + ru[i][j + 1] + ld[i + 1][m]; ans = gmax(ans, t); } } printf("%d\n", ans); return 0; }