您的位置:首页 > 其它

POJ 1661 Help Jimmy(动态规划)

2010-07-07 01:47 447 查看
//动态规划
//将板按高度排序
//记录到达每块板的左右端点所需的最少时间,和每块板从左右两边跳下去的下一块板指针
//从高到低不断迭代更新最少时间所需值
//注意边缘处理和直接落地的情况以及满足最大跳楼高度这些条件
#include<iostream>
#include<algorithm>
#define INF 1000000000;
using namespace std;
struct Plat
{
int x,y,h;
int R_next;//从右端点掉下去的下一块板
int L_next;//从左端点掉下去的下一块板
}P[1005];
int Left[1005],Right[1005];//用LEFT和RIGHT来记录从左端点和右端点到下一块板的最短时间
int t,N,X,Y,MAX;
int begin;
bool confirmL,confirmR;
bool cmp(Plat a,Plat b)
{
return a.h > b.h;//按板高度排序
}
void DP()
{
for(int i = begin;i <= N;++i)
{
int Lnext = P[i].L_next;
int Rnext = P[i].R_next;
if(Lnext == N)//如果从左边可以直接跳到地上
{
if(P[i].h <= MAX)//满足跳楼最大高度
Left
= Right
= min(Left[i] + P[i].h,Left
);
}
else
{
if(P[i].h - P[Lnext].h <= MAX)//如果到下一块板的高度差满足最大高度
{
Left[Lnext] = min(Left[i] + P[i].x - P[Lnext].x + P[i].h - P[Lnext].h,Left[Lnext]);//状态转移
Right[Lnext] = min(Left[i] + P[Lnext].y - P[i].x + P[i].h - P[Lnext].h,Right[Lnext]);
}
}
if(Rnext == N)//如果从右边可以直接跳到地上
{
if(P[i].h <= MAX)//满足跳楼最大高度
Left
= Right
= min(Right[i] + P[i].h,Left
);
}
else
{
if(P[i].h - P[Rnext].h <= MAX)//如果到下一块板的高度差满足最大高度
{
Left[Rnext] = min(Right[i] + P[i].y - P[Rnext].x + P[i].h - P[Rnext].h,Left[Rnext]);//状态转移
Right[Rnext] = min(Right[i] + P[Rnext].y - P[i].y + P[i].h - P[Rnext].h,Right[Rnext]);//状态转移
}
}
}
}

int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d",&N,&X,&Y,&MAX);
for(int i = 0;i <= N;++i)
Left[i] = Right[i] = INF;
P[0].x = -20000;
P[0].y = 20000;
P[0].h = 0;//初始化地面这块板
for(int i = 1;i <= N;++i)
{
scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].h);
}
sort(P,P+N+1,cmp);//按高度排序
for(int i = 0;i <= N;++i)//遍历所有模板,确定每块木板从左右端点跳下去的下一块木板
{
confirmL = confirmR = 0;
for(int j = i + 1;j <= N;++j)
{
if(confirmL && confirmR)	break;
if(P[i].x >= P[j].x && P[i].x <= P[j].y && !confirmL)
{
P[i].L_next = j;
confirmL = 1;//只确定一块
}
if(P[i].y >= P[j].x && P[i].y <= P[j].y && !confirmR)
{
P[i].R_next = j;
confirmR = 1;//只确定一块
}
}
}
for(int i = 0;i <= N;++i)//寻找起始点
{
if(i == N)//到N的话说明可以直接落地
{
Left[i] = Right[i] = Y;
begin = i;
}
else if(P[i].h <= Y && X >= P[i].x && X <= P[i].y)
{
begin = i;
Left[i] = (Y - P[i].h) + (X - P[i].x);//将初始时间状态记录下来
Right[i] = (Y - P[i].h) + (P[i].y - X);
break;
}
}
DP();
printf("%d/n",Left
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: