P2004 领地选择
题目描述
作为在虚拟世界里统帅千军万马的领袖,小Z认为天时、地利、人和三者是缺一不可的,所以,谨慎地选择首都的位置对于小T来说是非常重要的。
首都被认为是一个占地C*C的正方形。小Z希望你寻找到一个合适的位置,使得首都所占领的位置的土地价值和最高。
输入输出格式
输入格式:
第1行:三个正整数N,M,C,表示地图的宽和长以及首都的边长。
第2∼N+1行:第i+1行包含M个整数,表示了地图上每个地块的价值。价值可能为负数。
输出格式:
一行,两个整数X、Y,表示首都左上角的坐标。
输入输出样例
说明
对于60%的数据:N、M≤50。
对于90%的数据:N、M≤300。
对于100%的数据:N、M≤1000,C≤min(N,M)。
这一题就是前缀和呀……为什么会被加到dp里呢?我们先来思考一下要求下图的黑色部分面积,该怎么求呢?
![](https://cdn.luogu.org/upload/pic/6898.png)
枚举右下的这个点,就是(i,j);
很显然,应该是非白色部分减去红、灰色部分再减去蓝灰色部分加上灰色部分(因为灰色被减了两次),那么,我们假设f[i][j]表示从1,1到i,j所有数字之和,那么从i-c,j-c到i,j的值就是
f[i][j]-f[i-c][j]-f[i][j-c]+f[i-c][j-c];
解到这里,O(mn)的代码就可以构出了,代码如下(别全抄代码,自己动动脑):
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 int n,m,c,a[1001][1001],f[1001][1001],maxx=-0x7fffffff,x,y; 5 int main(){ 6 cin>>m>>n>>c; 7 for(int i=1;i<=m;i++) 8 for(int j=1;j<=n;j++) 9 scanf("%d",&a[i][j]); //输入矩阵 10 for(int i=1;i<=m;i++) 11 for(int j=1;j<=n;j++) 12 f[i][j]=a[i][j]+f[i-1][j]+f[i][j-1]-f[i-1][j-1]; //求前缀和(f[i][j]表示1,1到i,j数字之和) 13 for(int i=c;i<=m;i++) 14 for(int j=c;j<=n;j++) 15 if(f[i][j]-f[i-c][j]-f[i][j-c]+f[i-c][j-c]>maxx){ 16 maxx=f[i][j]-f[i-c][j]-f[i][j-c]+f[i-c][j-c]; //解释如上 17 x=i-c+1; 18 y=j-c+1; 19 } 20 cout<<x<<" "<<y; 21 }