intさわだんのBlack History

刹那的レジェンドになりたい。

第6回日本情報オリンピック 春合宿 1日目 問題3 「ショッピングモール」 (Mall)

二次元累積和やるだけです。

ある区間に何個-1があるかを二次元累積和で求められるようにし。
その区間の資源の合計も二次元累積和で求められるようにする。
DPでの解法もある(?)
計算量はO(n ^ 2).

累積和についてよくわからなかったら、

もし女子大生プログラマに『アルゴリズム』を図解で教えるとしたら - paiza開発日誌
を見てみてください。(「累積和」で検索して出てきただけだし読んでないけど...)

#include <bits/stdc++.h>

using namespace std;

int ch[1002][1002];
int d[1002][1002];
int m,n,a,b,ans=1000000000;
int main(){
	scanf("%d%d%d%d",&m,&n,&a,&b);

	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			scanf("%d",&d[i][j]);
			if(d[i][j] == -1)ch[i][j] = -1,d[i][j] = 0;
		}
	}
	for(int i = 2;i <= m;i++){
		d[1][i] += d[1][i-1];
		ch[1][i] += ch[1][i-1];
	}
	for(int i = 2;i <= n;i++){
		d[i][1] += d[i-1][1];
		ch[i][1] += ch[i-1][1];
	}
	for(int i = 2;i <= n;i++){
		for(int j = 2;j <= m;j++){
			d[i][j] += d[i-1][j] + d[i][j-1] -d[i-1][j-1];
			ch[i][j] += ch[i-1][j] + ch[i][j-1] - ch[i-1][j-1];
		}
	}
	for(int i = 1;i <= n - b;i++){
		for(int j = 1;j <= m - a;j++){
			if(ch[i+b-1][j+a-1] - ch[i-1][j+a-1] - ch[i+b-1][j-1] + ch[i-1][j-1] != 0)continue;
			ans = min(ans,d[i+b-1][j+a-1] - d[i-1][j+a-1] - d[i+b-1][j-1] + d[i-1][j-1]);
		}
	}
	printf("%d\n",ans);
	return 0;
}