您的位置:首页 > 其它

nyoj--61 传字条(一)(多线程dp)

2016-03-13 13:20 232 查看
nyoj 61

题意

m∗n的矩形方格,从左上角到右下角找到两条互不相交的路径(首尾两端除外),使得路径上的和最大。

题解

多线程dp,get new skill~

定义状态:dp(k,x1,y1,x2,y2)表示两人在第k步时分别到(x1,y1),(x2,y2)时的最大和。

状态转移:dp(k,x1,y1,x2,y2)=max{dp(k−1,x1−1,y1,x2−1,y2),dp(k−1,x1−1,y1,x2,y2−1),dp(k−1,x1,y1−1,x2−1,y2),dp(k−1,x1,y1−1,x2,y2−1)}+a(x1,y1)+a(x2,y2)

五维数组好可怕= =

两条路径都从左上角出发,每一步都只能向下或者向右,那么便有x1+y1=x2+y2,设这个和为k(其实就是第k步),则y1=k−x1,y2=k−x2,如此五维可以降到三维。

新的状态转移:dp(k,x1,x2)=max{dp(k−1,x1−1,x2−1)+dp(k−1,x1−1,x2)+dp(k−1,x1,x2−1)+dp(k−1,x1,x2)}+a(x1,k−x1)+a(x2,k−x2)

解为:dp(m+n−1,m,m−1) 或者 dp(m+n−1,m−1,m)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <map>
using namespace std;

#define setzero(arr) memset(arr, 0, sizeof(arr))

const int maxn = 55;
int   dp[2 * maxn][maxn][maxn], a[maxn][maxn];
int   t, n, m;

inline int Max(int a, int b, int c, int d)
{
return max(max(a, b), max(c, d));
}

void test(int a, int b, int c)
{
for(int i = 1; i <= a; ++i){
cout << "flag: " << i <<endl;
for(int j = 1; j <= b; ++j){
for(int k = 1; k <= c; ++k)
cout << dp[i][j][k] << " ";
cout << endl;
}
cout << endl;
}
}

void dpSolve(int r, int c)
{
setzero(dp);
for(int k = 2; k < r + c; ++k)      //一共要走 (r - 1 + c - 1) 步
{
//x1走“下线”,x2走“上线”,以横坐标标识
for(int x1 = 1; x1 <= r; ++x1)
for(int x2 = 1; x2 <= r; ++x2){

int y1 = k - x1, y2 = k - x2;
if(y1 <= 0 || y1 > c || y2 <= 0 || y2 > c || x1 == x2) continue;
dp[k][x1][x2] = Max(dp[k - 1][x1 - 1][x2 - 1], dp[k - 1][x1 - 1][x2],
dp[k - 1][x1][x2 - 1], dp[k - 1][x1][x2]) + a[x1][y1] + a[x2][y2];
}
}
//test(r + c - 1, r, r);
cout << dp[r + c - 1][r - 1][r] << endl;
//cout << dp[r + c - 1][r][r - 1] << endl;
}

//another version
void dpSolve1(int r, int c)
{
setzero(dp);
for(int k = 3; k < r + c; ++k)
{
for(int x1 = 1; x1 <= r; ++x1)
for(int x2 = x1 + 1; x2 <= r; ++x2){    //here differ

int y1 = k - x1, y2 = k - x2;
if(y1 <= 0 || y1 > c || y2 <= 0 || y2 > c || x1 == x2) continue;
dp[k][x1][x2] = Max(dp[k - 1][x1 - 1][x2 - 1], dp[k - 1][x1 - 1][x2],
dp[k - 1][x1][x2 - 1], dp[k - 1][x1][x2]) + a[x1][y1] + a[x2][y2];
}
}
int ans = Max(dp[r + c - 1][r - 1][r], dp[r + c - 1][r - 1][r - 1], dp[r + c - 1][r][r], dp[r + c- 1][r][r - 1]);
cout << ans << endl;
}

int main()
{
for(cin >> t; t--; )
{
cin >> m >> n;
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= n; ++j)
cin >> a[i][j];
dpSolve1(m, n);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nyoj dp middle+