习题:Dual Matrices(思路题/分治)

                                           tyvj1764

描述
一个N行M列的二维矩阵,矩阵的每个位置上是一个绝对值不超过1000的整数。
你需要找到两个不相交的A*B的矩形,使得这两个矩形包含的元素之和尽量大。
注:A*B的矩形指连续的A行、B列的子矩阵,或连续的B行、A列的子矩阵。不相交指两个矩形无公共元素。
格式
输入格式

第一行包括4个正整数N,M, A, B,之间由空格隔开。
以下N行,每行M个整数,之间由空格隔开,依次表示二维矩阵的每个元素。
输出格式

输出一行,一个整数,表示答案。如果找不到两个不相交的A*B的矩形,输出"Impossible"。
样例1
样例输入1[复制]

3 4 1 2
1 -1 3 4
-1 9 -1 1
9 8 5 2
样例输出1[复制]

25
限制
1s
提示
30%的数据满足,1 <= N, M <= 50.
另外30%的数据满足,A = B.
100%的数据满足,1 <= N, M <= 1 000, 1 <= A, B <=n,m

 

分析:

显然这两种有两种摆放方式,

一种是在水平线两侧,一种是在竖直线两侧。

对于第一种情况,我们枚举中间线的位置,然后将两边分开来看,求出上边区域内元素和最大的矩形,在求出下边区域元素和最大矩形,两者相加即为结果,然后找出所有值中最大的一个即可。第二种情况也一样

代码:

program t2;
var
  w:array[0..1001,0..1001]of longint;
  f,g:array[0..1001,1..2]of longint;
  n,i,m,j,x,a,b,t,ans:longint;
function max(x,y:longint):longint;
begin
  if x>y then max:=x else max:=y;
end;
begin
   assign(input,'t2.in');
   reset(input);
   assign(output,'t2.out');
   rewrite(output);
  readln(n,m,a,b);
   for i:=0 to n do
     begin f[i,1]:=-maxlongint div 2; f[i,2]:=-maxlongint div 2; end;
   for i:=0 to m do
     begin g[i,1]:=-maxlongint div 2; g[i,2]:=-maxlongint div 2; end;
  for i:=1 to n do
   for j:=1 to m do
    begin
      read(x); w[i,j]:=w[i,j-1]+w[i-1,j]-w[i-1,j-1]+x;
    end;
  for i:=1 to n do
    for j:=1 to m do
     begin
      if (i>=a)and(j>=b) then
       begin
         x:=w[i,j]+w[i-a,j-b]-w[i-a,j]-w[i,j-b];
         f[i,1]:=max(f[i,1],x); g[j,1]:=max(g[j,1],x);
       end;
      if (i>=b)and(j>=a) then
       begin
         x:=w[i,j]+w[i-b,j-a]-w[i-b,j]-w[i,j-a];
         f[i,1]:=max(f[i,1],x); g[j,1]:=max(g[j,1],x);
       end;
     end;
   for i:=n downto 1 do
    for j:=m downto 1 do
     begin
      if (i+a-1<=n)and(j+b-1<=m) then
       begin
         x:=w[i+a-1,j+b-1]+w[i-1,j-1]-w[i+a-1,j-1]-w[i-1,j+b-1];
         f[i,2]:=max(f[i,2],x); g[j,2]:=max(g[j,2],x);
       end;
      if (i+b-1<=n)and(j+a-1<=m) then
       begin
         x:=w[i+b-1,j+a-1]+w[i-1,j-1]-w[i+b-1,j-1]-w[i-1,j+a-1];
         f[i,2]:=max(f[i,2],x); g[j,2]:=max(g[j,2],x);
       end;
     end;
   if a>b then begin t:=a; a:=b; b:=t; end;
   ans:=-maxlongint;
   for i:=a+1 to n-a+1 do f[i,1]:=max(f[i,1],f[i-1,1]);
   for i:=n-a downto a do f[i,2]:=max(f[i,2],f[i+1,2]);
   for i:=a+1 to m-a+1 do g[i,1]:=max(g[i,1],g[i-1,1]);
   for i:=m-a downto a do g[i,2]:=max(g[i,2],g[i+1,2]);
   for i:=a to n-a do
    ans:=max(ans,f[i,1]+f[i+1,2]);
   for i:=a to m-a do
    ans:=max(ans,g[i,1]+g[i+1,2]);
   if ans>-maxlongint then writeln(ans) else writeln('Impossible');
   close(input); close(output)
end.
View Code

 

转载于:https://www.cnblogs.com/qtyytq/p/5869988.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值