您的位置:首页 > 其它

POJ 1661-Help Jimmy-dp

2016-05-25 18:59 459 查看
一道dp模拟题。

给n个板子和一个初始坐标xy,从x,y开始向下跳,有一个最高的下跳距离。

在板子上走和下跳都消耗时间。计算到达地面的最短时间。

把板子按高度排序

dp[i][0]表示到达第i块板子左边沿的时间,dp[i][1]表示到达右边沿的时间。

则 dp[i][0] = min(dp[k][0]+f(),dp[k][1]+f() ) k为小于i的可以跳到i上的板子。f()表示从k的左/右边沿到i的左边沿需要的时间。

dp[i][1] = min(dp[k][0]+f(),dp[k][1]+f())

注意判断k是否能跳到i上比较麻烦,k这一端的坐标在i内,且k还没有往下跳的板子,因为一块板子的一端只可能跳到唯一的一块板子,或者地面。

最后维护可以直接跳到地面的板子一端的dp值的最小值。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1000+10;
const int INF = 0x3f3f3f3f;

struct Table{
int l,r;
int height;
bool operator < (const Table &rhs) const
{
return height > rhs.height;
}
}table[maxn];

int N,X0,Y0,Max;
int T;
int dp[maxn][2];
int vis[maxn],next[maxn][2];

bool check(int i,int j)
{
if(table[j].height - table[i].height <= Max && table[j].height != table[i].height)
return true;
else
return false;
}

int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&N,&X0,&Y0,&Max);
for(int i=1;i<=N;i++)
{
scanf("%d%d%d",&table[i].l,&table[i].r,&table[i].height);
if(table[i].l > table[i].r)
swap(table[i].l,table[i].r);
}

sort(table+1,table+1+N);
memset(vis,0,sizeof vis);
memset(next,0,sizeof next);

for(int i=0;i<=N;i++)
dp[i][0] = dp[i][1] = INF;
int ans = INF;
int flag = 0;

for(int i=1;i<=N;i++)
{
if(Y0 - table[i].height > Max) break;
if(X0 >= table[i].l && X0 <= table[i].r)
{
dp[i][0] = Y0 - table[i].height + X0 - table[i].l;
dp[i][1] = Y0 - table[i].height + table[i].r - X0;
vis[i] = true;
flag = 1;
break;
}
}

if(!flag)
{
printf("%d\n",Y0);
continue;
}

for(int i=1;i<=N;i++)
{
for(int j=i-1;j>=1;j--) if(check(i,j) && vis[j])
{
if(!next[j][0] && table[j].l <= table[i].r && table[j].l >= table[i].l)
{
next[j][0] = true;
vis[i] = true;
dp[i][0] = min(dp[j][0]+table[j].height-table[i].height+table[j].l-table[i].l,dp[i][0]);
dp[i][1] = min(dp[j][0]+table[j].height-table[i].height+table[i].r-table[j].l,dp[i][1]);
}
if(!next[j][1] && table[j].r >= table[i].l && table[j].r <= table[i].r )
{
next[j][1] = true;
vis[i] = true;
dp[i][0] = min(dp[j][1]+table[j].height-table[i].height+table[j].r-table[i].l,dp[i][0]);
dp[i][1] = min(dp[j][1]+table[j].height-table[i].height+table[i].r-table[j].r,dp[i][1]);
}
}
//printf("l:%d r:%d \n",dp[i][0],dp[i][1]);
}

for(int i=N;i>=1;i--) if(vis[i] && table[i].height <= Max)
{
if(!next[i][0]) ans = min(ans,dp[i][0]+table[i].height);
if(!next[i][1]) ans = min(ans,dp[i][1]+table[i].height);

//printf("h:%d l:%d r:%d [%d,%d] \n",table[i].height,dp[i][0],dp[i][1],next[i][0],next[i][1]);
}
printf("%d\n",ans);
}
}


最近做了好多dp水题,然而不想上传,太水了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: