Help Jimmy 【POJ - 1661】DP

題目鏈接:https://vjudge.net/problem/POJ-1661
“Help Jimmy” 是在下圖所示的場景上完成的遊戲。
在這裏插入圖片描述

場景中包括多個長度和高度各不相同的平臺。地面是最低的平臺,高度爲零,長度無限。

Jimmy老鼠在時刻0從高於所有平臺的某處開始下落,它的下落速度始終爲1米/秒。當Jimmy落到某個平臺上時,遊戲者選擇讓它向左還是向右跑,它跑動的速度也是1米/秒。當Jimmy跑到平臺的邊緣時,開始繼續下落。Jimmy每次下落的高度不能超過MAX米,不然就會摔死,遊戲也會結束。
設計一個程序,計算Jimmy到底地面時可能的最早時間。

Input
第一行是測試數據的組數t(0 <= t <= 20)。每組測試數據的第一行是四個整數N,X,Y,MAX,用空格分隔。N是平臺的數目(不包括地面),X和Y是Jimmy開始下落的位置的橫豎座標,MAX是一次下落的最大高度。接下來的N行每行描述一個平臺,包括三個整數,X1[i],X2[i]和H[i]。H[i]表示平臺的高度,X1[i]和X2[i]表示平臺左右端點的橫座標。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1…N)。所有座標的單位都是米。

Jimmy的大小和平臺的厚度均忽略不計。如果Jimmy恰好落在某個平臺的邊緣,被視爲落在平臺上。所有的平臺均不重疊或相連。測試數據保證問題一定有解。
Output
對輸入的每組測試數據,輸出一個整數,Jimmy到底地面時可能的最早時間。
Sample Input
1
3 8 17 20
0 10 8
0 10 13
4 14 3
Sample Output
23

首先肯定是要按高度排序的
然後就是找狀態轉移方程了,f[i][0]表示落到第i塊板子左邊的最短時間,f[i][1]是到第i塊板子右邊的最短時間。
從第j塊板子左端可以落到板子i上時
f[i][0]=min(f[i][0],f[j][0]+t1)
f[i][1]=min(f[i][0],f[j][0]+t2) (t1,t2分別表示第j塊左端到第i塊左右的時間)
第j塊右端可以落到板子i上時與上面類似。
下面就只剩下怎麼判斷板子j是否可以落到板子i了(不在寫左右了,但是還是要區分的):
1.板子j高度要大於板子i,且高度差不能大於max
2.落點要在板子i的範圍內
3.也是最重要的一點,板子j到板子i的中間不能有其他板子,仔細看上面的圖,從一塊板子落下有且最多落到一塊板子,所以可以標記一下板子j可以落到那個板子,如果板子j沒有被標記,且滿足前兩個條件那它就可以落到i,狀態轉移即可,之後還要把j標記一下。
直接暴擊就行,複雜度O(n^2)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1010;
int n,m,t,x,y,st[N][2];//st[i][0]標記第i塊板子左端可以落到那個板子,st[i][1]就是右端
struct node
{
	int l,r,h;
}e[N];
ll f[N][2];
bool cmp(node a,node b)
{
	if(a.h==b.h) return a.l<b.l;//這裏其實無所謂加不加
	return a.h>b.h;
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>x>>y>>m;
		for(int i=1;i<=n;i++)
		{
			int a,b,c;
			cin>>a>>b>>c;
			e[i]={a,b,c};
		}
		e[0]={x,x,y};
		sort(e+1,e+n+1,cmp);
		memset(st,-1,sizeof st);
		memset(f,0x3f,sizeof f);
		f[0][0]=f[0][1]=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<i;j++)
			{
				if(e[j].h-e[i].h>0&&e[j].h-e[i].h<=m)//條件1
				{
					if(e[j].l>=e[i].l&&e[j].l<=e[i].r)//條件2
					{
						if(st[j][0]==-1)//條件3
						{
							f[i][0]=min(f[i][0],f[j][0]+e[j].h-e[i].h+e[j].l-e[i].l);
							f[i][1]=min(f[i][1],f[j][0]+e[j].h-e[i].h+e[i].r-e[j].l);
							st[j][0]=i;
						}
					}
					if(e[j].r>=e[i].l&&e[j].r<=e[i].r)//條件2
					{
						if(st[j][1]==-1)//條件3
						{
							f[i][0]=min(f[i][0],f[j][1]+e[j].h-e[i].h+e[j].r-e[i].l);
							f[i][1]=min(f[i][1],f[j][1]+e[j].h-e[i].h+e[i].r-e[j].r);
							st[j][1]=i;
						}
					}
				}
			}
		}
		ll ans=0x3f3f3f3f3f3f3f3f;
		for(int i=0;i<=n;i++)
			if(e[i].h<=m)
			{
				if(st[i][0]==-1) ans=min(ans,f[i][0]+e[i].h);
				if(st[i][1]==-1) ans=min(ans,f[i][1]+e[i].h);
			}
		cout<<ans<<endl;
	}
	
}```

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章