2008 noip 传纸条
https://www.luogu.org/problemnew/show/P1006
先放題
Description
題意很好理解
我們可以把它轉化成這樣
甲從原點開始,乙也從原點開始,找兩條權值最大的路,兩條路不能有重合的部分
方向只能向右或向下
這就是一個多進程的dp
我們可以考慮dp方程了
一般就會定為4維? ?dp[i1][j1][i2][j2]? 表示甲走到了i1,j1,乙走到了 i2 j2,能獲得的最大價值
看到題目,可以從題目性質考慮一下
它的遞推是斜著的
于是可以斜著考慮
每一個狀態是由上一條斜線遞推出來的
于是
dp方程就可以得出來了
dp[k][i][j]=max(max(dp[k-1][i-1][j],dp[k-1][i][j-1]),max(dp[k-1][i-1][j-1],dp[k-1][i][j]))+d[i][k-i]+d[j][k-j];
k表示一條斜線上的點,因為它的橫縱坐標之和是個定值,所以可以用橫縱坐標之和表示第一維
第二維表示甲已經走到了第i行
第三維表示乙已經走到了第j行
壓了一維之后甲的縱坐標是可以求出來的? 就是k-i
乙的縱坐標也可以得出 是 k-j
我們就可以寫這個題了
注意
1.一開始將dp賦初值為-1,表示所有點不可達
dp[2][1][1]=0;
2.因為遞推時有很多狀態是到達不了的,于是就可以continue
最后輸出dp[n+m-1][n-1][n]這個值就行了,因為相當于
這里的兩個綠點,反正最后一個點的權值為0
上代碼
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <algorithm> 5 #include <cstring> 6 using namespace std; 7 const int N=60; 8 int d[N][N],dp[5*N][N][N]; 9 int n,m; 10 int main() 11 { 12 scanf("%d %d",&n,&m); 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=m;j++) 15 { 16 scanf("%d",&d[i][j]); 17 } 18 memset(dp,-1,sizeof(dp)); 19 dp[2][1][1]=0; 20 for(int k=3;k<n+m;k++) 21 for(int i=1;i<n;i++) 22 { 23 for(int j=i+1;j<=n;j++) 24 { 25 dp[k][i][j]=max(max(dp[k-1][i-1][j],dp[k-1][i][j-1]),max(dp[k-1][i-1][j-1],dp[k-1][i][j])); 26 if(dp[k][i][j]==-1) 27 continue; 28 dp[k][i][j]+=d[i][k-i]+d[j][k-j]; 29 } 30 } 31 printf("%d\n",dp[n+m-1][n-1][n]); 32 }
這題就不愉快的解決了
轉載于:https://www.cnblogs.com/wzrdl/p/9776910.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的2008 noip 传纸条的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qtum量子链研究院:Plasma扩容方
- 下一篇: 树莓派3_win10下使用远程桌面连接与