[个人用]区间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;
}
posted @ 2025-05-15 22:16  Treow  阅读(9)  评论(1)    收藏  举报