nyoj--61 传字条(一)(多线程dp)
2016-03-13 13:20
232 查看
nyoj 61
定义状态: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)
题意
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; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow