這題是一道動規題目,原本打算在原矩陣上動手腳(預處理)
發現預處理只能找一條路的最大值!
於是,如何判重就非常重要了!
於是絞盡腦汁!!!!!!!!!
如果做標記的話預處理就沒有用了!
換乙個思路:
題目求來回兩條路的最大值,然而發現去的路反過來也可以當回來的路
意思就是選中一條路,既可以當回去的路,也可以當去的路
那麼我從起點出發,找到兩條到終點的路,讓兩條路的值最大
聯絡動規的特點:
對於每乙個狀態把所有的下乙個狀態可能的情況都列出來,取最優解
對於這道題,有四種狀態
所以狀態轉移方程為
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...