【DP】[Dota1001]地精工程师(GoblinTech)

描述

地精工程师的主要工作就是埋炸弹……
在一个M*N的矩形土地上,会有许多的小兵侵入,这些小兵都是钱啊,地精工程师怎能放弃这个刷钱的机会?于是,地精工程师决定埋一个遥控炸弹,等小兵都站好再引爆。
地精工程师的炸弹可以轰掉一个矩形区域,并收到所有这个矩形区域中小兵的钱。
有的小兵是魔法师……炸掉这个小兵可以让得到的钱乘2,如果炸掉多个这样的小兵,得到的钱就是原来的2^x倍(x为炸掉魔法师的个数)
地精工程师想知道,他最多能得到多少钱?

输入

第一行,两个数M,N
接下来M行N列的矩阵,表示炸掉每个位置上的小兵的钱
接下来一个数T
接下来T行,每行两个数x,y,表示位于x,y的小兵是魔法师

输出

一个数,表示最多得到多少钱

样例输入

3 3
-1 -1 1
1 -1 1
1 1 1
1
1 3

样例输出

6

提示

M,N<=100
T<=10
矩阵中的数在[-500,500]之间

【Solution】

这是一个最优子矩阵的变形,其中的矩阵价值是可变的,所以我们需要在原来的方程上多加一维。

(Zip后)F[i,j]表示前i个数中已经选了j个魔法兵所获得的最大金钱。B[i]存储每个格子的魔法兵数目。

F[i,j]←max{((F[i-1,j-b[i]]/2j-b[i])+a[i])*2j,a[i]*2b[i]}

不好意思,我的程序只能通过45%的测试点,其他都WA了…等要来数据再调吧…让人纠结啊。

【Code】

  1: Program GoblinTech(input,output);
  2:   var F:array[0..100,-10..10]of int64;
  3:       a:array[1..100,1..100]of longint;
  4:       Magic:array[1..100,1..100]of boolean;
  5:       aa,b,bb:array[0..100]of longint;
  6:       up,down,i,t,j,n,m,x,y:longint;
  7:       ans:int64;
  8:   Function max(a,b:Longint):longint;
  9:     begin
 10:       if a>b then exit(a) else exit(b);
 11:     end;
 12:   Procedure zip(up,down:longint);
 13:     var i,j:longint;
 14:     begin
 15:       fillchar(aa,sizeof(aa),0);
 16:       fillchar(b,sizeof(b),0);
 17:       for i:=1 to m do
 18:         begin
 19:           bb[i]:=bb[i-1];
 20:           for j:=up to down do
 21:             begin
 22:               inc(aa[i],a[j,i]);
 23:               if Magic[j,i] then begin inc(b[i]);inc(bb[i]);end;
 24:             end;
 25:         end;
 26:     end;
 27:   begin
 28:     readln(n,m);
 29:     for i:=1 to n do
 30:       for j:=1 to m do
 31:         read(a[i,j]);
 32:     readln(t);fillchar(Magic,sizeof(Magic),false);
 33:     for i:=1 to t do begin readln(x,y);Magic[x,y]:=true;end;
 34:     ans:=-5120000000;
 35:     for up:=1 to n do
 36:       for down:=1 to n do
 37:         begin
 38:           Zip(up,down);
 39:           fillchar(F,sizeof(F),0);
 40:           for i:=1 to m do
 41:             for j:=b[i] to bb[i] do
 42:               begin
 43:                 F[i,j]:=max(((F[i-1,j-b[i]] div (1<<(j-b[i])))+aa[i])*(1<<j),
 44:                              aa[i]*(1<<b[i]));
 45:                 if F[i,j]>ans then ans:=F[i,j];
 46:               end;
 47:         end;
 48:      writeln(ans);
 49:    end.
posted @ 2011-09-28 21:51  Loongint  阅读(351)  评论(0编辑  收藏  举报