nyoj 傳紙條(一)

2021-08-03 19:00:24 字數 1696 閱讀 6871

這題是一道動規題目,原本打算在原矩陣上動手腳(預處理)

發現預處理只能找一條路的最大值!

於是,如何判重就非常重要了!

於是絞盡腦汁!!!!!!!!!

如果做標記的話預處理就沒有用了!

換乙個思路:

題目求來回兩條路的最大值,然而發現去的路反過來也可以當回來的路

意思就是選中一條路,既可以當回去的路,也可以當去的路

那麼我從起點出發,找到兩條到終點的路,讓兩條路的值最大

聯絡動規的特點:

對於每乙個狀態把所有的下乙個狀態可能的情況都列出來,取最優解

對於這道題,有四種狀態

所以狀態轉移方程為

dp[x1][y1][x2][y2]=max(dp[x1][y1][x2][y2],dp[x1][y1][x2][y2],dp[x1][y1][x2][y2],dp[x1][y1][x2][y2])+map[x1][y1]+map[x2][y2]  其中(x1!=x2&&y1!=y2)

仔細分析一下狀態轉移方程

其實就是把每個點都根據上個點可能的值找最優解

但是這個狀態轉移方程是有問題的!!!

在題目中,必須保證兩條路的進度一樣,就是第一條路走幾步,第二條路就走幾步

所以我認為光憑上面的狀態轉移方程是沒辦法解出這道題的

那麼,就需要找乙個東西來表示走的步數

發現每走一步,x和y只能選乙個進行加1(以1,1為起點)

即x+y-2表示走的步數  比如 (1,2)  1+2-2=1

表示從(1,1)走一步就可以到(1,2)    

每次更新點的時候找這些點就可以了

還有乙個問題為陣列開的太大了!!!

簡直**!

那麼怎麼縮減?如果我記錄步數k,那麼我就可以用k和x1,x2推出y1,y2減少了一維

而且我這樣用k記錄步數更容易對更新的點進行操控!!!(具體看**)

下面上**:(完整狀態轉移方程在**中)

#include#include#includeusing namespace std;

int max4(int a,int b,int c,int d)

int map[55][55];

int map0[110][55][55];

int main()

}memset(map0,0,sizeof(map0));

map0[2][1][1]=map[1][1];

for(int k=2;k<=m+n;k++)//k-2表示步數,但是因為走0步其x+y為1,所以就這樣調整

map0[k][x1][x2]=max4(map0[k-1][x1-1][x2],map0[k-1][x1][x2-1],map0[k-1][x1-1][x2-1],map0[k-1][x1][x2])+map[x1][y1]+map[x2][y2];//狀態轉移方程}}

}printf("%d\n",map0[m+n-1][n][n-1]);//此處重點難點!!!

}}

重難點講解:

map0[m+n-1][n][n-1]表示到最後乙個點的前一步,m+n-1很好理解

但是為什麼是n 和n-1?   因為首先這表示的是x1和x2

而其範圍都是n,所以都和n有關

其次為什麼是n-1?

因為其必定是x1在下方,x2在上方!!!

而其如果走最後一步,x1必定是向右走,x2是向下走!!

nyoj 傳紙條(一)

費用流,這道題的關鍵在於建圖,看了一下大牛的部落格,想了這道題 總結一下思路 首先對於這種單一走路的題,一定要有拆點的思路對於這道題關建就在於 拆點,首先讓我們想一下,怎麼讓乙個點只走一下呢,這就是插電的精髓 然後加一條邊,容量為 1,費用為當前數值的一條邊,然後把這個點的右方 下方的點加一條邊,左...

nyoj 61 傳紙條(一)

分析 一道雙線程動態規劃題,與第六屆河南acm比賽的題類似.題意 小紙條從 1,1 傳到 m,n 再傳回來,並且路線不能交叉,使好感度之和最高.我們可以認為是同時找出兩條從 1,1 傳到 m,n 的不相交的路線.方法是 計算每一步情況下的情況,一條道路用i,j控制,另一條用x,y控制.從矩陣的角度看...

nyoj61 傳紙條(一) dp

思路 兩人乙個從左上角出發只能向右和向下,另一人從右下角出發只能向左和向上,可以看做兩人都是從右下角出發,且只能向左和向上傳紙條,並且兩條路徑不會相交,因為乙個人只會傳一次,那麼隨便畫乙個圖就能知道兩條路徑是閉合的圖形。因此我們可以定義dp x1,y1,x2,y2 是從 0,0 出發第一人到達 x1...