NOIP 2008 傳紙條(洛谷P1006,動態規劃遞推,滾動陣列)
阿新 • • 發佈:2018-11-19
題目連結:P1006 傳紙條
PS:傷心,又想不出來,看了大神的題解
AC程式碼:
#include<bits/stdc++.h> #define ll long long using namespace std; ll n,m,f[210][210],a[210][210]; int main() { ll i,j,k; cin>>n>>m; for (i=1;i<=n;++i) for (j=1;j<=m;++j) cin點選加號展開程式碼>>a[i][j]; f[1][2]=a[1][2]+a[2][1];//不管怎樣都會經過(1,2)和(2,1)先賦初值 //i是當前的點橫縱座標之和 //下面的迴圈是起碼2*3或者3*2棋盤才會進入,如果2*2及以下棋盤已經初定義了 for (i=4;i<n+m;++i)//至於i<n+m我是畫草圖才理解的 { for (j=min(i-2,n);j>=1;j--) //滾動陣列,i層和i-層有關,所以j,k要一直減小而不是增大,防止資料覆蓋 {//j=min(i-2,n)是在不超出的情況下找儘量小的能走的位置for (k=min(i-1,n);k>j;k--) {//k在j右邊,所以是i-1 if (j>1) //這裡的條件判斷貌似是不需要的,但加上更好 { f[j][k]=max(f[j][k],f[j-1][k]); } if (j>1&&k>1) { f[j][k]=max(f[j][k],f[j-1][k-1]); } if (k-1>j)//保證移動前的點沒有重合 { f[j][k]=max(f[j][k],f[j][k-1]); } //對於兩個都從上邊來的,其實是另一對(j,k)的兩個都從左邊來,所以不用寫了 f[j][k]+=a[j][i-j]+a[k][i-k];//把數字帶上 } } } cout<<f[n-1][n];//輸出左下角左邊和上邊兩個格的數字和就好了 return 0; }
談談我對這個思路的理解:
1.我們可以看成兩紙條同時從左上角原點出發
2.我們發現對於一個畫一條條斜線,斜線上的每個點橫座標加縱座標的和都相同
而且原點到同一條線上任意點要走的距離相同,那麼每走一步,紙條a和紙條b都在一條斜線上
為了防止相遇,我們可以假設b的橫座標k永遠大於a的橫座標j
而且,我們用i=n+m,那麼任意一點的橫座標=i-縱座標,縱座標同理,也就是橫座標+縱座標=i=n+m
3.那我們用i的變化來表示他們現在走到哪條斜線了,
這樣一來,就可以開始遞推,而且i只和i-1有關係,這是用滾動陣列的前提
4.對於陣列f[j,k],我們可以看成a走到(j,i-j),b走到(k,i-k)時撿起的總數字
5.然後賦初值,一開始第一步肯定是一個向右,一個向下,所以:
f[1][2]=a[1][2]+a[2][1];
不管怎樣都會經過(1,2)和(2,1)先賦初值
6.迴圈如何實現
for (i=4;i<n+m;++i)//至於i<n+m我是畫草圖才理解的 for (j=min(i-2,n);j>=1;j--) //滾動陣列,i層和i-層有關,所以j,k要一直減小而不是增大,防止資料覆蓋 //j=min(i-2,n)是在不超出的情況下找儘量小的能走的位置 for (k=min(i-1,n);k>j;k--)//k在j右邊,所以是i-1
第一維for表示要遞推的次數,從4開始是因為如果n,m為1,3就沒意義了,而m,n為2,2就已經靠初始化就夠了,不需要遞推
第二維是考慮紙條a的遞推,從大到小是因為每次都要用前面的資料賦值新的資料,所以這樣能防止覆蓋
第三維和第二維差不多
7.遞推式
if (j>1) //這裡的條件判斷貌似是不需要的,但加上更好 { f[j][k]=max(f[j][k],f[j-1][k]); } if (j>1&&k>1) { f[j][k]=max(f[j][k],f[j-1][k-1]); } if (k-1>j)//保證移動前的點沒有重合 { f[j][k]=max(f[j][k],f[j][k-1]); } //對於兩個都從上邊來的,其實是另一對(j,k)的兩個都從左邊來,所以不用寫了
解釋以下,這裡分別代表
a從左來,b從左來
a從上來,b從左來
a從左來,b從上來
有人回問那兩個都從上來去哪了?額,它其實在另外一個地方被算過了,下面上圖解釋
紅色和藍色表示兩個都從上面來,其實他們就等於黃色的那兩個地方的兩個都從左邊來
還有一個地方要注意的是:a從上來,b從左來,這時候要k-1>j,保證移動前的兩個點不是重合的
下面上個圖解釋一下,下圖是錯誤情況
8.輸出結果,只要輸出當a,b到最右下角那個點的左邊和上面的情況的值就好了
老是寫不出來DP,自閉了...