1. 程式人生 > 實用技巧 >動態規劃--lgP1004 方格取數,P1006 傳紙條

動態規劃--lgP1004 方格取數,P1006 傳紙條

1.方格取數:找到兩條路線使得獲得的總價值最大

定義狀態:f[i][j][l][k]表示第一個路線走到(i,j),第二個路線走到(l,k)的最大價值

狀態轉移:和數字三角形一樣f[i][j][l][k]=max(max(f[i][j-1][l][k-1],f[i-1][j][l][k-1]),max(f[i][j-1][l-1][k],f[i-1][j][l-1][k]))+a[i][j]+a[l][k];

但是題目規定取完的數會變成0,所以當(i,j)和(l,k)是同一個位置時要減去一個a[i][j]

程式碼:

 1 #include <iostream>
 2 #include <algorithm>
 3
#include <cstdio> 4 #include <cstring> 5 using namespace std; 6 int x,y,w,n; 7 const int maxn=10; 8 int a[maxn][maxn],f[maxn][maxn][maxn][maxn]; 9 int main(){ 10 scanf ("%d",&n); 11 while (scanf ("%d%d%d",&x,&y,&w)&&x!=0&&y!=0&&w!=0){ 12 a[x][y]=w;
13 } 14 for (int i = 1;i <= n;i++){ 15 for (int j = 1;j <= n;j++){ 16 for (int l = 1;l <= n;l++){ 17 for (int k = 0;k <= n;k++){ 18 f[i][j][l][k]=max(max(f[i][j-1][l][k-1],f[i-1][j][l][k-1]),max(f[i][j-1][l-1][k],f[i-1][j][l-1
][k]))+a[i][j]+a[l][k]; 19 if (i==l&&j==k) f[i][j][l][k]-=a[i][j]; 20 } 21 } 22 } 23 } 24 cout<<f[n][n][n][n]<<endl; 25 }

2.傳紙條

和上一道題一毛一樣嗷,惟一的區別是,上一道題去過的數還是可以走,只是沒貢獻,但是這一道題是取過的就不能走了,但是本質是相同的,那就在這裡證明一下。

動態規劃都知道是從一個狀態轉移到另一個狀態,如果現在(i,j)和(l,k)是同一個位置,那麼一個的貢獻為0,當前位置f[i][j][l][k]=f[i-1][j][l-1][k]|f[i-1][j][l][k-1]|f[i][j-1][l][k-1]|f[i][j-1][l-1][k];如果換個方向走,且這個方向沒走過,那麼就f[i][j][l][k]=f[i-1][j][l-1][k]|f[i-1][j][l][k-1]|f[i][j-1][l][k-1]|f[i][j-1][l-1][k]加上一個數一定>本身,max自動忽略另一個貢獻為0的方案。如果另一個方向貢獻還為0,我們在跳回上上一個點,如果他往(i,j)這個方向走,那麼貢獻一定為0,所以需要往另一個方向走才能加貢獻,如果還是為0,繼續向上走,總會有一個方向的貢獻不為0.所以每次我們在取max的時候,會自動忽略已經走過的路線。

程式碼:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 int x,y,w,n,m,mark,x1,x2,y1,y2;
 7 const int maxn=55;
 8 int a[maxn][maxn],f[maxn][maxn][maxn][maxn];
 9 int main(){
10     scanf ("%d%d",&n,&m);
11     for (int i = 1;i <= n;i++){
12         for (int j = 1;j <= m;j++){
13             scanf ("%d",&a[i][j]);
14             if (a[i][j]==0&&mark==0) {x1=i,y1=j;mark++;}
15             if (a[i][j]==0&&mark!=0) x2=i,y2=j; 
16         }
17     }
18     for (int i = x1;i <= x2;i++){
19         for (int j = y1;j <= y2;j++){
20             for (int l = x1;l <= x2;l++){
21                 for (int k = y1;k <= y2;k++){
22                     f[i][j][l][k]=max(max(f[i][j-1][l][k-1],f[i-1][j][l][k-1]),max(f[i][j-1][l-1][k],f[i-1][j][l-1][k]))+a[i][j]+a[l][k];
23                     if (i==l&&j==k) f[i][j][l][k]-=a[i][j];
24                 }
25             }
26         }
27     }
28     cout<<f[x2][y2][x2][y2]<<endl;
29 }