洛谷Oj-传纸条-多线程DP
来源:互联网 发布:java参考文献近五年的 编辑:程序博客网 时间:2024/05/19 19:30
问题描述:
小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。
学习资料:
http://blog.csdn.net/u011077606/article/details/43302987
AC代码:
int mat[100][100],dp[60][60][60][60];//dp[i][j][x][y]代表第一个人走到点(i,j)并且第二个人走到点(x,y)所获得好感度的最大值int main(){ int m,n; //输入 cin >> m >> n; for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) scanf("%d",&mat[i][j]); for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) for(int x = 1; x <= m; ++x) for(int y = 1; y <= n; ++y)//dp[i][j][x][y]可由四个状态转移而来,由于是求最大值所以不担心越界的问题 { int t1 = max(dp[i - 1][j][x][y - 1],dp[i][j - 1][x][y - 1]); int t2 = max(dp[i - 1][j][x - 1][y],dp[i][j - 1][x - 1][y]); dp[i][j][x][y] = max(t1,t2) + mat[i][j] + mat[x][y];//四个状态中的最大值再加上点(i,j)和(x,y)的好感度 if(i == x && j == y)//如果有交叉点,减去即可 dp[i][j][x][y] -= mat[i][j]; } printf("%d\n",dp[m][n][m][n]);//终点 return 0;}
解决方法:
在一开始我想到了先走一次,记录下路径并标记然后再走一次的方法。可是尝试了许多办法,记录路径难度太大。
走一次的代码:
int mat[100][100],dp[110][60][60];//dp[state][i][j]代表走到第state阶段中的点(i,j)所获得好感度的最大值int main(){ int m,n; //输入 cin >> m >> n; for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) scanf("%d",&mat[i][j]); for(int state = 3; state <= m + n; ++state)//将每一条副对角线视为一个阶段 for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) if(i + j == state)//如果属于这个阶段,就转移 { if(i - 1 < 1)//越界,但由于界外元素的值为0,故不判断也可以 dp[state][i][j] = dp[state - 1][i][j - 1] + mat[i][j]; else if(j - 1 < 1)//越界 dp[state][i][j] = dp[state - 1][i - 1][j] + mat[i][j]; else dp[state][i][j] = max(dp[state - 1][i][j - 1],dp[state - 1][i - 1][j]) + mat[i][j];//上方的点,左方的点 } printf("%d\n",dp[m + n][m][n]);//终点 return 0;}
实在是束手无策后,对照题解学习了一下,得知此题也叫做棋盘形DP。
一来一回等价于两次从左上角的点到右下角的点,所以将此问题看做是两张纸条同时向终点传
如果路径交叉,我们可以把它转化成不交叉的等价情形
此时含有交叉点的两条路径一定不是最终的答案,所以计算时只需要将这种情况下的值如实算出来
这道题因为有i + j = x + y的关系,所以还可以优化成三维
- 洛谷Oj-传纸条-多线程DP
- vijos P1493 传纸条 多线程dp
- CODEVS 1169 传纸条(多线程DP)
- 动态规划之传纸条(多线程dp)
- 【DP】洛谷 P1006 传纸条
- 【日常学习】【棋盘DP】【多线程DP】codevs1169 传纸条题解
- 传纸条 NOIP2008 洛谷1006 二维dp
- 【DP】[NOIP2008]传纸条
- wiki1169-传纸条(dp)
- voj1493 传纸条 dp
- DP - 传纸条
- 传纸条(dp)
- 传纸条[C++ DP]
- sdut oj 2615传纸条
- NYOJ61传纸条双线DP
- NYOJ61传纸条双线DP
- 传纸条(一) DP
- codevs1169 传纸条(棋盘dp)
- 数量加减栏
- 去东方,最好用的在线GO富集分析工具
- C# Aspose.Word 操作word文档【二】
- Python3零基础入门数据库篇003---把爬取到的数据存到数据库,带数据库去重功能
- SpringCloud: 断路器聚合监控(Hystrix Turbine)
- 洛谷Oj-传纸条-多线程DP
- 第二周项目一
- tablayout的简单使用
- php汉字转json格式不乱码
- Xcode 9
- BeanCopier系列之二:使用Converter
- Xcode 9 新特性有哪些
- Embeded linux之移植iptables
- MTK射频调试方法