vijos p1627(看櫻花)

先恭喜一下 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.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章