【DP】 hdu4362 Dragon Ball
来源:互联网 发布:手机淘宝发布宝贝教程 编辑:程序博客网 时间:2024/05/16 08:28
Dragon Ball
http://acm.hdu.edu.cn/showproblem.php?pid=4362
Problem Description
Sean has got a Treasure map which shows when and where the dragon balls will appear. some dragon balls will appear in a line at the same time for each period.Since the time you got one of them,the other dragon ball will disappear so he can only and must get one Dragon ball in each period.Digging out one ball he will lose some energy.Sean will lose |x-y| energy when he move from x to y.Suppose Sean has enough time to get any drogan ball he want in each period.We want to know the minimum energy sean will lose to get all period’s dragon ball.
Input
In the first line a number T indicate the number of test cases.Then for each case the first line contain 3 numbers m,n,x(1<=m<=50,1<=n<=1000),indicate m period Dragon ball will appear,n dragon balls for every period, x is the initial location of sean.Then two m*n matrix. For the first matrix,the number in I row and J column indicate the location of J-th Dragon ball in I th period.For the second matrix the number in I row and J column indicate the energy sean will lose for J-th Dragon ball in I-th period.
Output
For each case print a number means the minimum energy sean will lose.
Sample Input
13 2 52 34 11 31 11 34 2
Sample Output
8
题意:有一条线,有m周期,在每个周期在线上的n个点会出现一个龙珠,同时给你初始的点,在每个周期必须去取一个且只能取一个龙珠,取龙珠的消耗为当前点到龙珠所在的距离和挖取龙珠的消耗总和,问在m个周期取m个龙珠的最小消耗为多少。
题解:状态转移为dp[i][j]=min{dp[i-1][k]+|pos[i][j]-pos[i-1][k]|}+cost[i][j](1<=k<=n),这个需要o(n^3)的时间复杂度,如果人品够好还是能过的,但是这个明显不是正解。我们可以分pos[i][j]<pos[i-1][k]和pos[i][j]>pos[i-1][k]两种情况讨论,此时绝对值就可以去掉了,发现这个最值和j没有关系,我们做些预处理就可以提高效率了。
二分搜索版:
ps:g++能过,c++WA这个好神奇啊,猜测是二分写的有问题,求路过的大神指导。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define min(a,b) ((a)<(b)?(a):(b))#define max(a,b) ((a)>(b)?(a):(b))#define inf 0x7fffffff#define ab(x) ((x)>0?(x):-(x))struct point{ int mat; int dig;}node[55][1005];int dp[55][1005];int num[1010];int l[1005],r[1005];int n,m;bool tmp(const point &a,const point &b){ return a.mat<b.mat;}//二分查找求上界int find_upper(int x,int i){ if(x>node[i-1][m].mat) return -1; int lx=1,rx=m,mid; for(;rx>lx;) { mid=(lx+rx)/2; if(node[i-1][mid].mat>x) rx=mid; else if(node[i-1][mid].mat<x) lx=mid+1; else return mid; } return rx;}//二分查找求下界int find_lower(int x,int i){ if(x<node[i-1][1].mat) return -1; int lx=1,rx=m,mid; for(;rx>lx;) { mid=(lx+rx+1)/2; if(node[i-1][mid].mat<x) lx=mid; else if(node[i-1][mid].mat>x) rx=mid-1; else return mid; } return lx;}int main(){ int T; int x; scanf("%d",&T); for(; T--;) { scanf("%d%d%d",&n,&m,&x); for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) scanf("%d",&node[i][j].mat); for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) scanf("%d",&node[i][j].dig); for(int i=1;i<=n;++i) sort(node[i]+1,node[i]+m+1,tmp); //初始化 for(int i=2; i<=n; ++i) for(int j=1; j<=m; ++j) dp[i][j]=inf; for(int i=1; i<=m; ++i) dp[1][i]=ab(x-node[1][i].mat)+node[1][i].dig; for(int i=2; i<=n; ++i) { int minn=inf; for(int j=1;j<=m;++j) { if(minn>dp[i-1][j]-node[i-1][j].mat) minn=dp[i-1][j]-node[i-1][j].mat; l[j]=minn; } minn=inf; for(int j=m;j>=1;--j) { if(minn>dp[i-1][j]+node[i-1][j].mat) minn=dp[i-1][j]+node[i-1][j].mat; r[j]=minn; } for(int j=1; j<=m; ++j) { int rx=find_upper(node[i][j].mat,i); int lx=find_lower(node[i][j].mat,i); if(lx!=-1) dp[i][j]=min(dp[i][j],l[lx]+node[i][j].mat); if(rx!=-1) dp[i][j]=min(dp[i][j],r[rx]-node[i][j].mat); dp[i][j]+=node[i][j].dig; } } int ans=inf; for(int i=1; i<=m; ++i) ans=min(ans,dp[n][i]); printf("%d\n",ans); } return 0;}
单调队列版本:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define min(a,b) ((a)<(b)?(a):(b))#define max(a,b) ((a)>(b)?(a):(b))#define inf 0xfffffff#define ab(x) ((x)>0?(x):-(x))struct point{ int mat; int dig;} node[55][1005];int dp[55][1005];bool cmp(const point &a,const point &b){ return a.mat<b.mat;}int main(){ int T,x,n,m; scanf("%d",&T); for(; T--;) { scanf("%d%d%d",&n,&m,&x); for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) scanf("%d",&node[i][j].mat); for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) scanf("%d",&node[i][j].dig); for(int i=1; i<=n; ++i) sort(node[i]+1,node[i]+m+1,cmp); for(int i=2; i<=n; ++i) for(int j=1; j<=m; ++j) dp[i][j]=inf; for(int i=1; i<=m; ++i) dp[1][i]=ab(x-node[1][i].mat)+node[1][i].dig; for(int i=2; i<=n; ++i) { int idx=1,minn=inf;//下标和最值 for(int j=1; j<=m; ++j) { for(;idx<=m&&node[i][j].mat>=node[i-1][idx].mat;++idx) { minn=min(minn,dp[i-1][idx]-node[i-1][idx].mat); } dp[i][j]=min(dp[i][j],minn+node[i][j].mat); } idx=m,minn=inf;//下标和最值 for(int j=m; j>=1; --j) { for(;idx>=1&&node[i][j].mat<=node[i-1][idx].mat;--idx) { minn=min(minn,dp[i-1][idx]+node[i-1][idx].mat); } dp[i][j]=min(dp[i][j],minn-node[i][j].mat); } for(int j=1; j<=m; ++j) dp[i][j]+=node[i][j].dig; } int ans=inf; for(int i=1; i<=m; ++i) ans=min(ans,dp[n][i]); printf("%d\n",ans); } return 0;}
来源:http://blog.csdn.net/ACM_Ted
- 【DP】 hdu4362 Dragon Ball
- hdu4362 Dragon Ball(dp+单调队列优化)
- 2012 Multi-University Training Contest 7-1003 hdu4362 Dragon Ball
- HDU_3872 Dragon Ball dp
- hdu 4362 Dragon Ball(dp)
- hdu_4362 Dragon Ball (DP+单调栈)
- MUTC7 C - Dragon Ball 单调队列dp
- hdu 4362 Dragon Ball(优先队列+dp)
- hdu4326 Dragon Ball 单调队列优化Dp
- hdu 4362 Dragon Ball 很裸的DP
- hdu 4362 Dragon Ball 单调队列优化 dp
- HDU 4362 Dragon Ball(维护最小值DP优化)
- HDU 3872 Dragon Ball(DP+线段树+单调栈)
- hdu4362 dp + 单调队列优化
- HDU 3872 Dragon Ball
- hdu 3872 Dragon Ball
- HDU 4362 - Dragon Ball
- HDU-4363-Dragon Ball
- js正则表达式
- 参加ACM所需要的基础知识
- WebApp 开发中常用的代码片段
- SQL与T_SQL
- Java的形参与实参
- 【DP】 hdu4362 Dragon Ball
- 【倍增/强连通分量】暴走的猴子
- 复制构造函数与赋值操作符之间的区别
- 不可变的String对象
- java.io.IOException: File /home/hadoop/mapred/system/jobtracker.info could only be replicated to 0 n
- Acmer必看的26个对acm态度
- HDOJ 2844 Coins
- 《加密与解密》(第三版)【1】基础知识——小结
- Linux进程间通信IPC(一)-- pipe