打砖块

题意:

在刚开始的时候,有n行*m列的砖块,小红有k发子弹。小红每次可以用一发子弹,打碎某一列当前处于这一列最下面的那块砖,并且得到相应的得分。
如图所示:
打砖块_第1张图片
某些砖块在打碎以后,还可能将得到一发子弹的奖励。最后当所有的砖块都打碎了,或者小红没有子弹了,游戏结束。

思路:

一开始先把每一列求一个用j发子弹打出的最大值,然后一列一列的扫过去,
设f[i,j]为钱i列用了j发子弹的最大值,可以得出方程
f[i,j]:=max(f[i-1,k]+sum[i,j-k])sum为上面求出的i列用j发子弹的最大值

程序:

const
        maxn=250;
var
        k,i,j,n,m,ii:longint;
        c:char;
        a,b,f,s:array [0..maxn,0..maxn] of longint;
        flag:array [0..maxn,0..maxn] of boolean;
        ans:int64;
function max(x,y:int64):int64;
begin
        if x>y then exit(x)
               else exit(y);
end;

begin
        readln(n,m,k);
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        read(a[i,j],c,c);
                        if c='Y' then flag[i,j]:=true;
                end;
        end;

        for i:=1 to m do
                for j:=1 to n do
                begin
                        b[i,j]:=b[i,j-1]+a[n-j+1,i];
                        if (flag[n-j+1,i]) and (s[i,j-1]then s[i,j]:=s[i,j-1]
                                         else s[i,j]:=s[i,j-1]+1;
                end;
        for i:=0 to maxn do
                for j:=0 to maxn do
                        f[i,j]:=-1;

        for i:=1 to n do
                if s[1,i]<=k then f[1,s[1,i]]:=b[1,i];
        f[1,0]:=0;
        for i:=1 to m-1 do
                for j:=0 to k do
                begin
                        if f[i,j]=-1 then continue;
                        f[i+1,j]:=max(f[i+1,j],f[i,j]);
                        for ii:=1 to n do
                        begin
                                if s[i+1,ii]+j>k then break;
                                f[i+1,s[i+1,ii]+j]:=max(f[i,j]+b[i+1,ii],f[i+1,s[i+1,ii]+j]);
                                ans:=max(ans,f[i+1,s[i+1,ii]+j]);
                        end;
                end;
        writeln(ans);
end.

你可能感兴趣的:(动态规划,纪中成神之路)