关路灯,洛谷之提高历练地,动态规划TG.lv(1)(3-2)

时间:2021-03-08 18:41:17

正题

      第四题:关路灯

      这题主要就是用区间Dp(莫队可做?)。

      那么一个以关灯区间的状态有两种,记录左端点和记录右端点。

      我们用f[i][j][0]来表示当前是在左端点。

      用f[i][j][1]来表示当前是在右端点。

      一个点在左端点时,到他的状态有:f[i+1][j][1],f[i+1][j][0](从上个区间的右端点和左端点过来);

      一个点在右端点时,到他的状态有:f[i][j-1][1],f[i][j-1][0](从上个区间的右端点和左端点过来);

      那么当在走过来的同时,会浪费一定的电,如果当前要 求左端点,从上个区间左端点过来那么就浪费了距离乘瓦数。其他的同理,做一个前缀和a[i]来统计一下0到i的距离即可。

#include<cstdio>
#include<cstdlib>
#include<cstring>

int n,k;
struct node{int x,y;};
node s[55];
long long f[55][55][2];
int qian[55];

long long min(long long x,long long y)
{
	return x<y?x:y;
}

int main()
{
	scanf("%d %d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&s[i].x,&s[i].y);
	qian[1]=s[1].y;
	for(int i=2;i<=n;i++)
		qian[i]=qian[i-1]+s[i].y;
	memset(f,63,sizeof(f));
	f[k][k][1]=0;
	f[k][k][0]=0;
	for(int l=1;l<=n-1;l++)
		for(int i=1;i+l<=n;i++)
		{
			int j=i+l;
			long long a=f[i+1][j][0]+(s[i+1].x-s[i].x)*(qian[n]-qian[j]+qian[i]);
			long long b=f[i+1][j][1]+(s[j].x-s[i].x)*(qian[n]-qian[j]+qian[i]);
			f[i][j][0]=min(a,min(f[i][j][0],b));;
			a=f[i][j-1][0]+(s[j].x-s[i].x)*(qian[n]-qian[j-1]+qian[i-1]);
			b=f[i][j-1][1]+(s[j].x-s[j-1].x)*(qian[n]-qian[j-1]+qian[i-1]);
			f[i][j][1]=min(a,min(f[i][j][1],b));
		}
	printf("%d",min(f[1][n][0],f[1][n][1]));
}