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

来源:互联网 发布:c语言深度剖析 pdf 编辑:程序博客网 时间:2024/04/29 14:18

nyoj 61

题意

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

题解

多线程dp,get new skill~
定义状态:dp(k,x1,y1,x2,y2)表示两人在第k步时分别到(x1,y1),(x2,y2)时的最大和。
状态转移:dp(k,x1,y1,x2,y2)=max{dp(k1,x11,y1,x21,y2),dp(k1,x11,y1,x2,y21),dp(k1,x1,y11,x21,y2),dp(k1,x1,y11,x2,y21)}+a(x1,y1)+a(x2,y2)
五维数组好可怕= =
两条路径都从左上角出发,每一步都只能向下或者向右,那么便有x1+y1=x2+y2,设这个和为k(其实就是第k步),则y1=kx1,y2=kx2,如此五维可以降到三维。
新的状态转移:dp(k,x1,x2)=max{dp(k1,x11,x21)+dp(k1,x11,x2)+dp(k1,x1,x21)+dp(k1,x1,x2)}+a(x1,kx1)+a(x2,kx2)
解为:dp(m+n1,m,m1) 或者 dp(m+n1,m1,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 versionvoid 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;}
0 0
原创粉丝点击