codevs 1043 方格取数 (DP)
来源:互联网 发布:呼叫中心排班软件 编辑:程序博客网 时间:2024/06/04 19:19
题目描述 Description
设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):
某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入描述 Input Description
输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出描述 Output Description
只需输出一个整数,表示2条路径上取得的最大的和。
样例输入 Sample Input
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
样例输出 Sample Output
67
思路一:
我们设f[i,j,k,l]表示第一条路走到(i,j),第二条路走到(k,l)的路线。
那么状态转移方程很好得出:
f[i,j,k,l]=max{f[i-1,j,k-1],f[i-1,j,k,l-1],f[i,j-1,k-1,l],f[i,j-1,k,l-1]}+(i==k&&j==l ? a[i][j] : a[i][j]+a[k][l])
值得注意的是:最后加上这个值的时候要注意如果路径走到同一点不能重复统计。
时间复杂度:O(n4),空间复杂度O(n4),对于本题n<=10完全足够。
思路二:
虽然思路一对于本题完全足够,但是如果n的范围大些的话,就无法办到了。
针对思路一,我们发现了问题,有一些状态是可以合并的,最重要的是:思路一,我们是同时开始走的,那么不必记录向右、向下的具体路径,只需要记录步数,显然,两条路的步数是统一的,然后再记录向下或向右的次数,就能根据这两者推算出向下或向右的次数。
那么设f[i,j,k]表示走到了第i步,第一条路径向右走了j步,第二条路径向右走了k步。
那么f[i,j,k]=max{f[i-1,j,k],f[i-1,j-1,k],f[i-1,j-1,k-1],f[i-1,j,k-1]}+(j==k ? a[i-j+1][i] : a[i-j+1][j]+a[i-k+1][k]);
显然,我们也要判断路径是否走到同一点,所以有后面的那个if( ? : 三目运算符)
时间复杂度:O(2n3),空间复杂度O(2n3),优化了一维。从n的四方优化至n的三方,是一个很大的进步。
至于代码,只要思路知道了,就无所谓了。
因为n才10,搜索也可以
思路摘自:点击打开链接
#include<iostream>#include<cstring>#include<cstdio>using namespace std;typedef long long ll;const int maxn = 15;int a[maxn][maxn];int dp[maxn][maxn][maxn][maxn];int main(void){int n;while(cin >> n){int x, y, z;memset(a, 0, sizeof(a));memset(dp, 0, sizeof(dp)); while(scanf("%d%d%d", &x, &y, &z), x+y+z)a[x][y] = z;for(int x1 = 1; x1 <= n; x1++)for(int y1 = 1; y1 <= n; y1++)for(int x2 = 1; x2 <= n; x2++)for(int y2 = 1; y2 <= n; y2++){dp[x1][y1][x2][y2] = max( max(dp[x1-1][y1][x2-1][y2], dp[x1-1][y1][x2][y2-1]), max(dp[x1][y1-1][x2-1][y2], dp[x1][y1-1][x2][y2-1]) ) + a[x1][y1];if(x2 != x1 && y2 != y1) dp[x1][y1][x2][y2] += a[x2][y2];}printf("%d\n", dp[n][n][n][n]);}return 0;}
1 0
- codevs 1043 方格取数 (DP)
- codevs 1043 方格取数(棋盘型DP)
- codevs 1043 方格取数 (dfs or dp)
- codevs-1043 方格取数
- codevs 1043方格取数
- 【codevs 1043】方格取数
- codevs 1169 传纸条 && 1043 方格取数(棋盘DP)
- codevs 1227 方格取数
- [DP]方格取数
- 蓝桥杯 方格取数 (多线程DP)
- noip2000 方格取数(多重DP)
- 命运 (DP方格取数)
- [luogu1004]方格取数(dp,亚瑟)
- 方格取数(1) (状态dp)
- Codevs 1043 ==洛谷 P1004 方格取数
- 【codevs 1227】方格取数2(费用流)
- 【codevs 1902】方格取数3(最小割)
- CodeVS 1907 方格取数 3 (ISAP)
- 每天一个linux命令(1):grep 命令
- 常用sql语句
- day74_mongoDB
- java对象数组的增删改查
- NYOJ--113--字符串替换
- codevs 1043 方格取数 (DP)
- 深度学习(五十八)caffe移植至mxnet
- GBK和UTF8之间的转换 C语言
- 用事件和观察者模式解决经典面向对象题目:猫叫鼠跑人醒的题目
- 字符集与编码五之代码单元及length方法
- POJ 1113 Wall 凸包(模板题)
- Sass/Scss学习
- Android 4.0 Launcher2源码分析——Workspace切换AllApps流程
- unity中调用dll(char*,以及带有函数指针的参数)方法总结