1. 程式人生 > >codevs 1373 射命丸文(矩陣字首和)

codevs 1373 射命丸文(矩陣字首和)

題目描述 Description
在幻想鄉,射命丸文是以偷拍聞名的鴉天狗。當然,文文的照相機可不止能夠照相,還能夠消除取景框裡面所有的彈幕。假設現在文文面前有一塊N行M列的彈幕群,每一個單位面積內有分值有num[i][j]的彈幕。相機的取景框可以將一塊R行C列的彈幕消除,並且得到這一塊區域內所有彈幕的分值(累加)。現在文文想要取得儘可能多的分值,請你計算出她最多能夠得到的分值。

輸入描述 Input Description
第1行:4個正整數N,M,R,C 第2..N+1行:每行M個正整數,第i+1行第j個數表示num[i][j]

輸出描述 Output Description


第1行:1個整數,表示文文能夠取得的最大得分

樣例輸入 Sample Input
3 5 2 3
5 2 7 1 1
5 9 5 1 5
3 5 1 5 3

樣例輸出 Sample Output
33

資料範圍及提示 Data Size & Hint
對於60%的資料:1 <= N,M <= 200
對於100%的資料:1 <= N,M <= 1,000 1 <= R <= N, 1 <= C <= M 1 <= num[i][j] <= 1000
保證結果不超過2,000,000,000

題解:最暴力的做法就是列舉每一個子矩陣求和找最大值,這樣顯然會超時。我們可以用矩陣字首和來做這道題。我們讀入的時候順便求一下矩陣字首和,然後就可以直接用。那麼我們怎麼通過矩陣字首和求子矩陣的和呢?其實跟字首和差不多,詳見下圖:
這裡寫圖片描述
矩陣4的和等於最大的矩陣減去((矩陣1+矩陣2)+(矩陣1+矩陣3)- 矩陣1),矩陣字首和就是這樣233,然後我們就可以O(1)詢問某個子矩陣的和,是不是很神奇╮(╯▽╰)╭。

程式碼如下

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int
sum[1010][1010],map[1010][1010]; int main() { int n,m,r,c,maxx=0; scanf("%d%d%d%d",&n,&m,&r,&c); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&map[i][j]); sum[i][j]=map[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];//求矩陣字首和 } for(int i=1;i<=n-r+1;i++) for(int j=1;j<=m-c+1;j++) if(sum[i+r-1][j+c-1]-sum[i+r-1][j-1]-sum[i-1][j+c-1]+sum[i-1][j-1]>maxx)//找子矩陣和的最大值 maxx=sum[i+r-1][j+c-1]-sum[i+r-1][j-1]-sum[i-1][j+c-1]+sum[i-1][j-1]; printf("%d",maxx); return 0; }