四維dp,傳紙條,方格取數
阿新 • • 發佈:2020-08-18
四維dp例題
四維dp便是維護4個狀態的dp方式
拿題來說吧。
1. 洛谷P1004 方格取數
#include<iostream> #include<cstdio> using namespace std; const int maxn=12; int n; int map[maxn][maxn]; int dp[maxn][maxn][maxn][maxn]; int main(){ cin>>n; int x,y,z; while(cin>>x>>y>>z&&(x!=0||x!=0||z!=0)){ map[x][y]=z; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) for(int l=1;l<=n;l++){ dp[i][j][k][l]=max(dp[i-1][j][k-1][l],max(dp[i-1][j][k][l-1],max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1])))+map[i][j]+map[k][l]; if(i==k&&j==l) dp[i][j][k][l]-=map[k][l]; } } cout<<dp[n][n][n][n]; return 0; }
本題便是一個四維dp例題
分析題目
發現維護兩個dp陣列或者進行兩次dp不是很現實
觀察到資料範圍較小
便可以考慮四維dp
我們將走兩次抽象成兩個人同時走
我們以dp[i] [j] [k] [l]表示第一個人走到i j
第二個人走到 k l 時的總體最大值
我們便對i j k l 進行列舉
因為兩人所走道路不能重合
所以當 i=k j=l時減去多加的那個就可以
2. 洛谷P1006 傳紙條
#include<iostream> using namespace std; const int maxn=90; int n,m; int map[maxn][maxn]; int dp[maxn][maxn][maxn][maxn]; int main(){ cin>>m>>n; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ cin>>map[i][j]; } } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) for(int k=1;k<=m;k++) for(int l=1;l<=n;l++){ dp[i][j][k][l]=max(dp[i-1][j][k-1][l],max(dp[i-1][j][k][l-1],max(dp[i][j-1][k-1][l],dp[i][j-1][k][l-1])))+map[i][j]+map[k][l]; if(i==k&&j==l) dp[i][j][k][l]-=map[k][l]; } } cout<<dp[m][n][m][n]; return 0; }
基本就是同一題
雙倍經驗
還有滾動陣列優化,
以後再更新