[个人用]区间DP 思路整理
P1220 关路灯
题目链接 参考文章
我想着必须要从起始位置开始拓展,怀疑这是否真的是区间DP。
看了题解后理解了,可以用左右端点拓展的那种区间DP解决。
DP数组存的是完成这个区间的最小功率,故初值赋无穷大。到达区间的一端i,上一步来源可能是去掉i的区间的左端点或者右端点。然后时间的增加,用前缀和算出已经关闭了的区间的功率,再与功率总和做差,可以得到未关闭的灯的功率(注意i也要考虑,因为它还没关)。再与距离差(即反映时间)相乘就得到了功率。两种可能性取最小值即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl '\n'
// const int MAX;
// const int MOD;
int N,C;
int p[55],pre[55],dp[55][55][2];
void solve(){
cin>>N>>C;
for(int i=1;i<=N;i++){
int a,b;
cin>>a>>b;
p[i]=a,pre[i]=pre[i-1]+b;
}
memset(dp,0x3f,sizeof dp);
dp[C][C][0]=dp[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;
//[0]左[1]右
dp[l][r][0]=min(dp[l+1][r][0]+(p[l+1]-p[l])*(pre[N]-(pre[r]-pre[l])),
dp[l+1][r][1]+(p[r]-p[l])*(pre[N]-(pre[r]-pre[l])));
dp[l][r][1]=min(dp[l][r-1][1]+(p[r]-p[r-1])*(pre[N]-(pre[r-1]-pre[l-1])),
dp[l][r-1][0]+(p[r]-p[l])*(pre[N]-(pre[r-1]-pre[l-1])));
}
}
cout<<min(dp[1][N][0],dp[1][N][1])<<endl;
}
signed main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// int times;cin>>times;
// while(times--)
solve();
return 0;
}

浙公网安备 33010602011771号