洛谷P10726 [GESP202406 八级] 空间跳跃 题解

题目传送门。

第一次自己做出一道绿色的 DP!!!!
刚开始的时候,你会发现这其实就是一个很朴素的 DP,一开始先按高度将挡板从小到大排序,然后将 \(s\)\(t\) 更改为排序后的位置,设 \(f_{i,j}\) 表示当前在第 \(i\) 个档板的 \(j\) 位置到达第 \(t\) 号挡板的最短距离,然后状态转移为 \(f_{i,j} = \min(f_{k,l_i}+h_i-h_k+j-l_i,f_{o,r_i}+h_i-h_o+r_i-j)\)\(k\) 就是能从 \(l_i\) 掉落到的挡板编号,\(o\) 是能从 \(r_i\) 掉落到的挡板编号,虽然正确,但是你会发现时间复杂度原地起飞,通过十分困难,不过洛谷机子这么好应该能过,但是你会发现其实你每次掉落你的位置只会在 \(l_i,r_i\) 中,所以最多只需要将所有的 \(l_i,r_i\) 当做 DP 数组的第二维求就行了,所以空间复杂度和时间复杂度就都全部降下来了,然后这题就做完了……

由于本人很唐,所以找到能掉落挡板位置的方法比较唐氏,就是使用区间覆盖最大值的方法,当然也可以直接往前找,时间复杂度差别应该只是个常数。

注意事项:

  • 记得特判 \(s<t\) 的情况!!
  • 记得特判不能转移的情况!!

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3+5;
int f[N][N];
struct node
{
	int l;
	int r;
	int h;
	int id;
}a[N];
int cmp(node x,node y)
{
	return x.h<y.h;
}
int ans[N];
int maxx[N];
signed main()
{
	memset(f,0x3f,sizeof(f));
	int n,s,t,cnt = 0;
	scanf("%d %d %d",&n,&s,&t);
	for(int i = 1;i<=n;i++)
	{
		scanf("%d %d %d",&a[i].l,&a[i].r,&a[i].h);
		a[i].id = i;
		ans[++cnt] = a[i].l;
		ans[++cnt] = a[i].r;
	}
	sort(ans+1,ans+cnt+1);
	sort(a+1,a+n+1,cmp);
	for(int i = 1;i<=n;i++)
	{
		if(a[i].id == s)
		{
			s = i;
		}
		if(a[i].id == t)
		{
			t = i;
		}
	}
	if(s<t)
	{
		printf("-1");
		return 0;
	}
	int l = lower_bound(ans+1,ans+cnt+1,a[t].l)-ans;
	int r = upper_bound(ans+1,ans+cnt+1,a[t].r)-ans-1;
	for(int i = l;i<=r;i++)
	{
		f[t][i] = 0;
	}
	for(int i = t+1;i<=s;i++)
	{
		int l = lower_bound(ans+1,ans+cnt+1,a[i-1].l)-ans;
		int r = upper_bound(ans+1,ans+cnt+1,a[i-1].r)-ans-1;
		for(int j = l;j<=r;j++)
		{
			maxx[j] = max(maxx[j],i-1);
		}
		int ll = lower_bound(ans+1,ans+cnt+1,a[i].l)-ans;
		int rr = upper_bound(ans+1,ans+cnt+1,a[i].r)-ans-1;
		int lll = maxx[ll];
		int rrr = maxx[rr];
		for(int j = ll;j<=rr;j++)
		{
			if(lll!=0)//找不到掉落到的挡板不能进行转移
			{
				f[i][j] = min(f[i][j],ans[j]-a[i].l+a[i].h-a[lll].h+f[lll][ll]);
			}
			if(rrr!=0)//找不到掉落到的挡板不能进行转移
			{
				f[i][j] = min(f[i][j],a[i].r-ans[j]+a[i].h-a[rrr].h+f[rrr][rr]);
			}
		}
	}
	int weizhi = lower_bound(ans+1,ans+cnt+1,a[s].l)-ans;
	printf("%d",f[s][weizhi] == f[0][0]?-1:f[s][weizhi]);
	return 0;
}

所以说这题有绿吗,我怎么感觉暴力 DP 能过???虽然没试过……

posted @ 2025-03-07 21:05  林晋堃  阅读(322)  评论(0)    收藏  举报