hdu 4362 Dragon Ball(dp)
来源:互联网 发布:wind 淘宝 编辑:程序博客网 时间:2024/05/18 01:59
http://acm.hdu.edu.cn/showproblem.php?pid=4362
题意:有m个阶段,每个阶段都有n个龙珠,当在某一阶段选择一个龙珠,该阶段其他龙珠都会消失。给出两个m*n的矩阵,第一个矩阵表示消灭第i个阶段第j个龙珠的位置,第二个矩阵表示取第i个阶段第j个龙珠消耗的能量,同时当第x个位置到第个位置需要消耗 | y - x|的能量。问最后每个阶段取走一个龙珠最小的能量消耗。
思路:状态转移方程很容易,dp[i][j] = min(dp[i-1][k] + abs( pos[i-1][k] - pos[i][j] ) ) + energy[i][j]。
但由于n较大,想着会TLE。试着敲出来,果真TLE。改了改细节,然后加了个内联函数水过。
#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;int n,m,x;int pos[55][1010],ener[55][1010],dp[55][1010];inline int chk(int x){ if(x < 0) return -x; return x;}int main(){ int test; scanf("%d",&test); while(test--) { scanf("%d %d %d",&n,&m,&x); for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) scanf("%d",&pos[i][j]); } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) scanf("%d",&ener[i][j]); } for(int j = 0; j < m; j++) dp[0][j] = chk(pos[0][j]-x) + ener[0][j]; for(int i = 1; i < n; i++) { for(int j = 0; j < m; j++) { int tmp = INF; for(int k = 0; k < m; k++) { int sum = dp[i-1][k] + chk(pos[i-1][k] - pos[i][j]); if(tmp > sum) tmp = sum; } dp[i][j] = tmp+ener[i][j]; } } int ans = INF; for(int j = 0; j < m; j++) ans = min(ans, dp[n-1][j]); printf("%d\n",ans); } return 0;}
再看状态转移方程,dp[i][j] = min(dp[i-1][k] + abs( pos[i-1][k] - pos[i][j] ) ) + energy[i][j],发现dp[i][j]与energy[i][j] 和 pos[i][j]无关,去绝对值的方法是排序,对pos排序后,用单调队列存上一行 dp[i-1][k] +(-) pos[i-1][k]的值,最后取队首(最大)即可。该题的正解应该是单调队列,做了hdu437后,又回来A一下。
#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;struct node{ int pos; int ener; bool operator < (const struct node &tmp)const { return pos < tmp.pos; }}point[55][1010];int dp[55][1010];int abss(int x){ if(x < 0) return -x; return x;}int n,m,x;int main(){ int test; scanf("%d",&test); while(test--) { scanf("%d %d %d",&n,&m,&x); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d",&point[i][j].pos); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) scanf("%d",&point[i][j].ener); sort(point[i]+1,point[i]+1+m); } memset(dp,INF,sizeof(dp)); for(int j = 1; j <= m; j++) dp[1][j] = abss(point[1][j].pos - x) + point[1][j].ener; for(int i = 2; i <= n; i++) { int minn = INF; int index = 1; for(int j = 1; j <= m; j++) { while(index <= m && point[i-1][index].pos <= point[i][j].pos) { minn = min(minn, dp[i-1][index]-point[i-1][index].pos); index++; } dp[i][j] = minn + point[i][j].pos; } minn = INF; index = m; for(int j = m; j >= 1; j--) { while(index >= 1 && point[i-1][index].pos > point[i][j].pos) { minn = min(minn,dp[i-1][index] + point[i-1][index].pos); index--; } dp[i][j] = min(dp[i][j], minn-point[i][j].pos); dp[i][j] += point[i][j].ener; } } int ans = dp[n][1]; for(int i = 2; i <= m; i++) ans = min(ans, dp[n][i]); printf("%d\n",ans); } return 0;}
0 0
- hdu 4362 Dragon Ball(dp)
- hdu 4362 Dragon Ball(优先队列+dp)
- HDU 4362 - Dragon Ball
- hdu 4362 Dragon Ball
- hdu 4362 Dragon Ball 很裸的DP
- hdu 4362 Dragon Ball 单调队列优化 dp
- HDU 4362 Dragon Ball(维护最小值DP优化)
- HDU_3872 Dragon Ball dp
- 【DP】 hdu4362 Dragon Ball
- HDU 4362 Dragon Ball 线段树
- HDU 3872 Dragon Ball
- hdu 3872 Dragon Ball
- HDU-4363-Dragon Ball
- HDU 3872 Dragon Ball(DP+线段树+单调栈)
- hdu_4362 Dragon Ball (DP+单调栈)
- MUTC7 C - Dragon Ball 单调队列dp
- hdu4326 Dragon Ball 单调队列优化Dp
- hdu4362 Dragon Ball(dp+单调队列优化)
- 微信第三方服务平台源码分析——每个Action与模块的对应关系
- 《算法概论》思维导图
- OpenCV实现验证otsu算法
- Medoo Query的使用:执行SQL语句
- django用表单实现图片爬虫
- hdu 4362 Dragon Ball(dp)
- Activity的用法(三):开启网页 (没有弹出浏览器,不清楚是什么原因)
- Android通过PHP连接MySQL(读取)
- AJAX 数据库实例
- 多按键设计的标准思路
- 蓝桥杯 排它平方数
- Linux C语言调用C++动态链接库
- TF-IDF 简介
- C++常见面试题