Description
GZOI队员们到X镇游玩。X镇是一个很特别的城镇,它有m+1条东西方向和n+1条南北方向的道路,划分成m*n个区域,这些区域标从北到南、从西到东的坐标标识为从坐标 (1,1) 到坐标(m,n)。 GZOI队员们预先对这m*n个区域打分V(i,j)(分数可正可负)。分数越高表示他们越想到那个地方,越低表示他们越不想去。为了方便游玩,队员们需要选定一个连续的区域集合作为活动范围。例如,如果他们选择了最西北的区域(m1,nl)和最东南(m2,n2)区域(m1<=m2,n1<=n2),那他们的活动范围是 {D(i,j)|m1<=i<=m2,n1<=j<=n2},其游览总分则为这些活动范围的区域总分。 GZOI队员们希望他们活动范围内的区域的分值总和最大。你的任务是编写一个程序,求出他们的活动范围(m1,nl),(m2,n2〉。
Input
输入第一行为整数m(1<=m<=200),n(1<=n<=200),用空格隔开 下面为m行,每行有n列整数,其中第i行第j列的整数,代表V(i,j),每个整数之间用空格隔开,每个整数的范围是 [-200000,200000],输入数据保证这些整数中,至少存在一个正整数。
Output
输出只有一行,为最高的分值。
Solution
看代码吧
代码
c++暴力开O2过版:
1 #pragma GCC optimize(2)
2 #pragma GCC optimize(3)
3 #include<bits/stdc++.h>
4 using namespace std;
5
6 int sum[207][207];
7 long long ans;
8 int n,m;
9
10 int main(){
11 scanf("%d %d",&n,&m);
12 for (int i=1;i<=n;i++)
13 for (int j=1;j<=m;j++){
14 scanf("%d",&sum[i][j]);
15 sum[i][j]=sum[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
16 }
17 ans=0;
18 for (int i=1;i<=n;i++)
19 for (int j=1;j<=m;j++)
20 for (int l=i;l<=n;l++)
21 for (int r=j;r<=m;r++)
22 if (ans<sum[l][r]-sum[i-1][r]-sum[l][j-1]+sum[i-1][j-1])
23 ans=sum[l][r]-sum[i-1][r]-sum[l][j-1]+sum[i-1][j-1];
24 printf("%lld",ans);
25 }
Pascal O(n3)版
1 var
2 sum:array[0..201,0..201] of longint;
3 n,m,ans:longint;
4 procedure init;
5 var
6 i,j:longint;
7 begin
8 readln(n,m);
9 for i:=1 to n do
10 for j:=1 to m do
11 begin
12 read(sum[i,j]);
13 sum[i,j]:=sum[i,j-1]+sum[i,j];
14 end;
15 end;
16
17 function max(o,p:longint):longint;
18 begin
19 if o>p then exit(o);
20 exit(p);
21 end;
22
23 procedure main;
24 var
25 i,j,k,t:longint;
26 begin
27 ans:=0;
28 for i:=1 to m do
29 for j:=i to m do
30 begin
31 t:=0;
32 for k:=1 to n do
33 begin
34 t:=t+sum[k,j]-sum[k,i-1];
35 ans:=max(ans,t);
36 if t<0 then t:=0;
37 end;
38 end;
39 end;
40
41 begin
42 init;
43 main;
44 writeln(ans);
45 end.
本文介绍了一个关于GZOI队员在X镇游玩时如何选择最优活动范围的问题。通过构建二维矩阵并使用动态规划的方法,实现了在限定条件下找到区域内得分总和最大的连续子矩形,最终给出最优解。
5395

被折叠的 条评论
为什么被折叠?



