您的位置:首页 > 其它

poj1661 Help Jimmy(DP)

2015-09-14 21:11 309 查看
题目链接:

http://poj.org/problem?id=1661

题目大意:中文题。

思路:这个题目可以用DP。

对于这个问题,要求总的时间最短。如果在某一块板上,可以选择往左或者往右走。如果此刻我们知道了往左走和往右走到达地面所用的最短时间,那么我们就可以判断出往哪个方向走是最优的。如果我们设置dp[i][j],dp[0][i]表示在第i块板上往左走的最短时间,dp[1][i]表示在第i块板上往右走的最短时间,可以得到状态转移方程:

dp[0][i]=h[i]-h[j]+min(dp[0][j]+x1[j]-x1[i],dp[1][j]+x2[i]-x1[j]);

dp[1][i]=h[i]-h[j]+min(dp[0][j]+x2[i]-x1[j],dp[1][j]+x2[j]-x2[i]);

注意要对木板的高度进行排序,这里可以从小到大进行排序。

这里还有一个要点就是:可能他可以直接跳。所以要额外判断。

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int min(int a,int b)
{
if(a<b)return a;
else return b;
}
struct node {
int x1,x2,h;
}p[1005];
bool cmp(node a,node b)
{
if(a.h==b.h)return a.x1<b.x1;
return a.h<b.h;
}
int main()
{
int T,i,j,k,dp[2][20005],n,x,y,MAX,sum,as;
bool f;
scanf("%d",&T);
while(T--)
{
sum=0;
memset(dp,0,sizeof(dp));
scanf("%d%d%d%d",&n,&x,&y,&MAX);
for(i=1;i<=n;i++)
scanf("%d%d%d",&p[i].x1,&p[i].x2,&p[i].h);
sort(p+1,p+1+n,cmp);

p[n+1].x1=x;p[n+1].x2=x;
p[n+1].h=y;       //最后一个赋为起点。
for(i=1;i<=n+1;i++)         //从低到高来看,求得dp的最优值
{
f=false;
for(j=i-1;j>0;j--)     //左
{

if(p[i].h-p[j].h<=MAX&&p[i].h>p[j].h)   //这里要判断是否不超过最大高度。
{
if(p[j].x1<=p[i].x1&&p[i].x1<=p[j].x2)    //判断是否可以跳到下一块,一旦可以就跳下去,因为也只能跳下去。
{	dp[0][i]=p[i].h-p[j].h+min(dp[0][j]+p[i].x1-p[j].x1,dp[1][j]+p[j].x2-p[i].x1);
f=true;
break;
}

}
}
if(p[i].h-p[0].h>MAX&&f==false)dp[0][i]=99999999;    //如果没有一块可以跳,那么就直接跳到地面
else if(f==false)dp[0][i]=p[i].h;
f=false;
for(j=i-1;j>0;j--)           //右
{
if(p[i].h-p[j].h<=MAX&&p[i].h>p[j].h)
{
if(p[i].x2>=p[j].x1&&p[j].x2>=p[i].x2)
{dp[1][i]=p[i].h-p[j].h+min(dp[0][j]+p[i].x2-p[j].x1,dp[1][j]+p[j].x2-p[i].x2);
f=true;
break;}
}
}
if(p[i].h-p[0].h>MAX&&f==false)dp[1][i]=99999999;
else if(f==false)dp[1][i]=p[i].h;
}
printf("%d\n",min(dp[0][n+1],dp[1][n+1]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: