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