題目鏈接: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;
}
}```