這一道題的思路很簡單,暴力dp都可以過(就是用4個for),但是有可能會爆空間。
先來講講暴力dp的思路吧
這一道題可以看成是求乙個人從左上角到右下角走兩次所經過路線的最大值,所以用兩個for來列舉第一次走的橫縱座標,另外兩個for來列舉第二次做的橫縱座標,
一共分四種情況:
1、f[i][j][k][l]=f[i-1][j][k-1][l]//兩條路都是從上面走下來的
2、f[i][j][k][l]=f[i][j-1][k][l-1]//兩條都是從左邊走過來的
3、f[i][j][k][l]=f[i-1][j][k][l-1]//一條是從上面走下來的,一條是從左邊走過來的
4、f[i][j][k][l]=f[i][j-1][k-1][l]//一條是從左邊走過來的,一條是從上面走下來的
可以推出狀態轉移方程:f[i][j][k][l]=max(max(f[i-1][j][k-1][l],f[i][j-1][k][l-1]),max(f[i-1][j][k][l-1],f[i][j-1][k-1][l]))+a[i][j];
完整**:
#include #include #include #include int m,n;
int a[55][55];
ll dp[55][55][55][55];
int main()
}for(int i=1;i<=m;i++)}}
}printf("%lld\n",dp[m][n][m][n]);
return 0;
}
這種方法既浪費空間,又容易超時,所以我們對它進行了時間的優化
因為兩個人到目的地的步數相同,所以列舉步數和兩個人的橫座標之後,就可以算出兩個人縱座標,
但是狀態轉移方程就要複雜一點:(因為列舉步數,就要加上每個人的位置的值)
f[k][i][j]=max(max(f[k-1][i][j],f[k-1][i-1][j-1]),max(f[k-1][i-1][j],f[k-1][i][j-1]))+a[i][k+1-i]+a[j][k+1-j];
#include #include #include #include int m,n;
int a[55][55];
ll dp[105][55][55];
int main()
}for(int k=1; k<=m+n-1; k++)}}
printf("%lld\n",dp[m+n-1][m][m]);
return 0;
}
這樣,既節省了空間,又能給程式提速。最終空間為100*50*50。
還有一種最優的辦法:列舉乙個人的橫縱座標和另乙個人的橫座標,因為步數相同,就可以算出另乙個人的縱座標
用同樣的辦法,可以找出狀態轉移方程。
f[i][j][k]=max(max(f[i-1][j][k-1],f[i-1][j][k]),max(f[i][j-1][k-1],f[i][j-1][k]))+a[i][j]+a[k][l];//l=i+j-k;
最終空間為50*50*50。
#include#includeusing namespace std;
int a[60][60],f[60][60][60],n,m,i,j,k,l;
int main()
printf("%d",f[n][m][n]);
}
動態規劃 傳紙條
小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排做成乙個m行n列的矩陣,而小淵和小軒被安排在矩陣對角線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手裡,小淵坐在矩陣的左上角,座標 1,1 小軒坐在矩...
傳紙條 動態規劃
小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排做成乙個m行n列的矩陣,而小淵和小軒被安排在矩陣對角 線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手裡,小淵坐在矩陣的左上角,座標 1,1 小軒坐在...
藍橋杯 傳紙條 (動態規劃)
題目大意 給一矩陣,兩人分別在左上和右下,兩人傳遞紙條,規定左上的人只能向右和向下傳遞,右下的人只能向左和向上傳遞,兩者路徑不能相交,求兩條路徑的權值總和最大是多少。題目解答 我們轉化一下思想,題目中說由左上方到右下方來回,我們可以看作是從左上方找兩條不相交的路徑到右下方。這裡我們可以好比是兩個紙條...