洛谷P1220 关路灯 区间dp

给出 n ≤ 50 n\leq50 n50个路灯,给出每个路灯的功率,路灯所在的位置,以及你的初始路灯所在的位置。然后求按照一定的顺序关灯,使得总共消耗的能量最少。
走过的地方一定会关灯,也就是说对于一段区间的答案,主人公一定是站在左端点或者右端点的。用 f l , r , 0 ∣ 1 f_{l,r,0|1} fl,r,01表示 [ l , r ] [l,r] [l,r]这段路灯被关掉站在左边|右边位置最小值。然后直接转移。
这个题比较难想,应该说对于区间连续的问题应该要往这个方向考虑。
应该是 O ( n 2 ) O(n^2) O(n2),数据规模给这么小不知道为啥。

#include
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=55;
int pos[N],w[N];
ll sum[N]; 
ll f[N][N][2];
ll get(int l,int r) {
	return sum[r]-sum[l-1];
}
int main() {
	int n,c;
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++) {
		scanf("%d%d",&pos[i],&w[i]);
		sum[i]=sum[i-1]+w[i];
	} 
	for(int i=1;i<=n;i++) {
		for(int j=i;j<=n;j++) {
			f[i][j][0]=1e15;
			f[i][j][1]=1e15;
		}
	}
	f[c][c][0]=f[c][c][1]=0;
	for(int len=2;len<=n;len++) {
		for(int l=1;l+len-1<=n;l++) {
			int r=l+len-1;
			f[l][r][0]=min(f[l][r][0],f[l+1][r][0]+(pos[l+1]-pos[l])*(get(1,l)+get(r+1,n)));
			f[l][r][0]=min(f[l][r][0],f[l+1][r][1]+(pos[r]-pos[l])*(get(1,l)+get(r+1,n)));
			f[l][r][1]=min(f[l][r][1],f[l][r-1][1]+(pos[r]-pos[r-1])*(get(1,l-1)+get(r,n)));
			f[l][r][1]=min(f[l][r][1],f[l][r-1][0]+(pos[r]-pos[l])*(get(1,l-1)+get(r,n)));
		}
	}
	printf("%lld\n",min(f[1][n][0],f[1][n][1]));
	return 0;
}

你可能感兴趣的:(比赛题解)