vijos p1627(看樱花)

来源:互联网 发布:淘宝直播间申请 编辑:程序博客网 时间:2024/06/02 09:02

先恭喜一下 vijos 升级成2,0 版本 恭喜恭喜。

描述

“妹妹背着洋娃娃,走到花园看樱花” – 我整个人都Hello kitty了。
好了,闲话就说到这里,已知:这是一个1×N的花园(虽然比较奇怪),被分成了N个格子,每个格子里有一种神奇的樱花(我也不知道为什么神奇,反正洋娃娃看着高兴),看到第i个格子上的花洋娃娃会得到不同的满足度Ci(每个花的满足度只被计算一次)。现在妹妹会背着洋娃娃从任意格子走进花园,当然从第i个格子进去会消耗Di个单位的满足度,然后游历花园,在一个格子向右走需要耗费R个单位的满足度,向左走需要耗费L个单位的满足度,最后从第i个格子出花园又要耗费Fi个单位的满足度。
接下来,我们需要设计一套游历方案,使得最终获得的总满足度最高(太低的话洋娃娃会……)

格式

输入格式

第一行依次给出三个正整数N,L,R。
第二行有N个整数,第i个数为Di。
第三行有N个整数,第i个数为Fi。
第四行有N个整数,第i个数为Ci。

输出格式

仅需要输出一行包括一个整数,表示最大获得的满足度为多少。


首先,这道题目是一道动规题,一开始呢,根本想不到怎么动规。 可能一看到动规的题目,我就想用一个二维数组f[i,j]来 表示 从第 i 个点到第j 个点的最大满意值,会想到f[i,j]与f[i,j-1], f[i,j+1], f[i+1,j],f[i-1,j] 有联系,好吧,只能说我还没弄清楚。

看到这道题的题解后,发现这里的dp不是直接dp f[i,j];

具体分析:

有 i,j 两点, 设起点为i 终点为 j,且i<j, 因为满意度只能计算一次,则从i走到j共有以下几种走法:

1.直接从i 走到j 。

2.从i向左走再走回i再走到j(说不定能多拿一点满意度)。

3.从i向右走到j再向右走再向左走回到j(理由同上)。

4. 2点和3点综合,从i点向左走再走回i,然后从i向右走到j再向右走再向左走回到j。(理由同上)。

如果直接算的话,会很麻烦,所以我们弄一个预处理:

弄一个数组q[i],表示由1 到i 的满意度总和(不计代价)。

两个数组:

一个z[i],表示 由i向左走再走回来能够多拿的满意度(计代价)。

一个y[i],与z[i]一样,只不过方向向右。

若 i 为起点 j 为终点

我们可以知道 如果 i>j 则 s[i,j]=q[i]-q[j-1]+y[i]+z[j]-(i-j)*l-d[i]-f[j]

                              如果i<j      s[i,j]=q[j]-q[i-1]+y[j]+z[i]-(j-i)*r-d[i]-f[j]
我们不确定 y和z 是否能够加上去,如果他为负,我们我不能加,否则不是最优解。
判断的话就有点麻烦,所以我们可以这样:

若 z[i]or y[i]<0 就 把他赋值为0。

这样就算为负我们加上去 也没问题了。

程序:

program p1627aaa;type        arr=array[0..1010]of longint;        arrr=array[0..1010,0..1010]of longint;var        i,j,k,l,m,n,r,maxx:longint;        s:arrr;        q,c,d,f,z,y:arr;function max(a,b:longint):longint;begin        if a>b then exit(a)        else exit(b);end;begin        maxx:=-maxlongint;        read(n,l,r);        for i:=1 to n do read(d[i]);        for i:=1 to n do read(f[i]);        for i:=1 to n do read(c[i]);        for i:=1 to n do                for j:=1 to n do                        s[i,j]:=-maxlongint;        for i:=1 to n do        q[i]:=q[i-1]+c[i];        for i:=1 to n do                begin                z[i]:=-maxlongint;                y[i]:=-maxlongint;                end;        for i:=1 to n do                begin                for j:=1 to i do                        begin                        z[i]:=max(z[i],q[i]-q[j-1]-(i-j)*(l+r)-c[i]);                        end;                if z[i]<0 then z[i]:=0;                end;        for i:=1 to n do                begin                for j:=n downto i do                        begin                        y[i]:=max(y[i],q[j]-q[i-1]-(j-i)*(l+r)-c[i]);                        end;                if y[i]<0 then y[i]:=0;                end;        for i:=1 to n do                for j:=1 to n do                        begin                        if i>j then s[i,j]:=q[i]-q[j-1]+y[i]+z[j]-(i-j)*l-d[i]-f[j]                        else                        s[i,j]:=q[j]-q[i-1]+y[j]+z[i]-(j-i)*r-d[i]-f[j];                        if s[i,j]>maxx then maxx:=s[i,j];                        end;        write(maxx);end.


原创粉丝点击