codeforces.com/problemset/problem/213/C
2015-06-12 21:32
78 查看
虽然一开始就觉得从右下角左上角直接dp2次是不行的,后面还是这么写了WA了
两次最大的并不一定是最大的,这个虽然一眼就能看出,第一次可能会影响第二次让第二次太小。
这是原因。
5
4 32 1 18 41
47 38 7 43 43
48 23 39 40 23
26 39 33 5 36
31 29 7 26 47
这组数据是结果。
走完第一遍成
0 32 1 18 41
0 38 7 43 43
0 0 0 0 0
26 39 33 5 0
31 29 7 26 0
这样倒着走回去一定会经过0导致第二遍小很多。
正确走法
5
0 32 1 18 41
0 38 7 43 43
0 23 39 40 23
0 0 0 5 36
31 29 0 0 0
然后
5
0 0 1 18 41
0 0 7 43 43
0 0 0 0 0
0 0 0 5 0
31 29 0 0 0
这样和为508比两次取最大的482还大。
完全想不到怎么弄了。上一次求两次和最短路的走过了后就不能走,也想成两次跑最小,也是跪,结果应该用最小费用流。
这个也是没发现,不管怎么走一定每次确定步数后都会在同一条对角线上。
所以可以一条对角线一条一条的推。然而要同时确定两条路,走过去再走回来就等于走过去两条路,经过同一个点的时候只取一次。
dp[d][i][j]表示到第d条对角线时第一条路在i行,第二条路在j行最大的和能取多大,一路推到最后,这里可以用滚动数组dp内存就只有n*n了。
两次最大的并不一定是最大的,这个虽然一眼就能看出,第一次可能会影响第二次让第二次太小。
这是原因。
5
4 32 1 18 41
47 38 7 43 43
48 23 39 40 23
26 39 33 5 36
31 29 7 26 47
这组数据是结果。
走完第一遍成
0 32 1 18 41
0 38 7 43 43
0 0 0 0 0
26 39 33 5 0
31 29 7 26 0
这样倒着走回去一定会经过0导致第二遍小很多。
正确走法
5
0 32 1 18 41
0 38 7 43 43
0 23 39 40 23
0 0 0 5 36
31 29 0 0 0
然后
5
0 0 1 18 41
0 0 7 43 43
0 0 0 0 0
0 0 0 5 0
31 29 0 0 0
这样和为508比两次取最大的482还大。
完全想不到怎么弄了。上一次求两次和最短路的走过了后就不能走,也想成两次跑最小,也是跪,结果应该用最小费用流。
这个也是没发现,不管怎么走一定每次确定步数后都会在同一条对角线上。
所以可以一条对角线一条一条的推。然而要同时确定两条路,走过去再走回来就等于走过去两条路,经过同一个点的时候只取一次。
dp[d][i][j]表示到第d条对角线时第一条路在i行,第二条路在j行最大的和能取多大,一路推到最后,这里可以用滚动数组dp内存就只有n*n了。
#include <bits/stdc++.h> using namespace std; #define ll long long const int N = 305; const ll mod = 1e9 + 7; const double eps = 1e-12; int a ; int dp[2] ; int main() { int n;cin >> n; for (int i = 1;i <= n;i++) for (int j = 1;j <= n;j++) cin >> a[i][j]; memset(dp, -2, sizeof dp); dp[1][1][1] = a[1][1]; int now = 1; for (int d = 2;d < n + n;d++) { now ^= 1; for (int i = max(1,d-n+1);i <= min(n,d);i++) for (int j = max(1,d-n+1);j <= min(n,d);j++) { for (int x = i - 1;x <= i;x++) { for (int y = j - 1;y <= j;y++) { if (x >= max(1, d - n) && x <= min(n, d - 1) && y >= max(1,d - n) && y <= min(n, d - 1)) { int val = a[i][d - i + 1] + a[j][d - j + 1]; if (i == j)val /= 2; dp[now][i][j] = max(dp[now][i][j], dp[now ^ 1][x][y] + val); } } } } for (int i = 0;i <= n;i++) for (int j = 0;j <= n;j++)dp[now ^ 1][i][j] = -1000000000; } cout << dp[now] ; return 0; }
相关文章推荐
- Sidekiq基础的基础
- Sparse Representation Classification速度记录
- 不到100行代码实现一个简单的推荐系统
- 可重入函数与不可重入函数概念以及编写规范
- 33.对学生结构体的数据进行修改
- 冒泡排序算法(优化版)
- “渴了么”软件详细说明书
- SpringMVC输入校验
- 冒泡排序算法
- 编译 android-x86-4.4 各种找不到,解决方法
- 百度地图API制作类似 百度地图的路线导航界面并实现简单的路线规划功能
- 让TableViewSection在Plan的模式下不悬浮
- Veins 数据包收发基本流程简单总结
- 动态规划:从新手到专家
- 冒泡排序算法(初级版)
- HLJU 1042 Fight (种类并查集)
- “渴了么”软件需求规格说明书
- [FZYZOJ 1200] 路由器安置
- ioctl错误引出的open和fopen的区别
- drp错误集锦---“Cannot return from outside a function or method”