【动态规划】P3842 [TJOI2007]线段

由于每行的线段都需要走完,且不能向上走,所以对于走完每一行,只有两种可能 1)在线段右侧 2)在线段左侧

然后就可以基于这样的特点去更新下一行

对于第i行,如果结束在左端点,那么它可能是上一行从右端点下来,走到左侧;也可能是上一行的左侧走到当前行右侧位置,再下来走到左面,就可以以此dp了

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+5;
int n,l[maxn],r[maxn],f[maxn][2];
int main()
{
	freopen("a.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
	memset(f,0x3f,sizeof(f));
	f[1][0]=r[1]*2-l[1]-1; f[1][1]=r[1]-1;
	for(int i=2;i<=n;i++)
	{
		f[i][0]=min(min(f[i][0],f[i-1][0]+abs(l[i-1]-r[i])+r[i]-l[i]+1),f[i-1][1]+abs(r[i-1]-r[i])+r[i]-l[i]+1);
		f[i][1]=min(min(f[i][1],f[i-1][0]+abs(l[i-1]-l[i])+r[i]-l[i]+1),f[i-1][1]+abs(r[i-1]-l[i])+r[i]-l[i]+1);
	}	
	printf("%d\n",min(f[n][0]+n-l[n],f[n][1]+n-r[n])); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/andyc_03/article/details/107620741