#区间dp,动态规划#codevs 1258 洛谷 1220 关路灯

这篇博客主要讲解了如何利用动态规划(区间DP)来解决codevs 1258和洛谷1220的关路灯问题。博主分析了dp状态转移方程,其中dp[i][j][k]表示区间i到j的灯全关闭时,老王在i或j处所浪费的电量。关键在于计算val(i, j),公式为val(i, j) = (locj - loci) × (1 + ∑i-1a[i] + j+1∑na[i]),详细代码实现也在文中给出。" 126229140,10227230,使用JS实现时间轴驱动的多元素动画,"['javascript', 'css3', '前端开发', '动画库', '声明式动画']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

分析

d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]代表区间 i i i j j j的灯已经全部关闭时老王在 i i i ( k = = 0 ) (k==0) (k==0) j j j ( k = = 1 ) (k==1) (k==1)的时间点已经浪费的电量
那么

dp[i][j][0]=min(dp[i+1][j][0]+val(i,i+1,i,j+1),dp[i+1][j][1]+val(i,j,i,j+1)),
        dp[i][j][1]=min(dp[i][j-1][0]+val(i,j,i-1,j),dp[i][j-1][1]+val(j-1,j,i-1,j));

问题是val怎么求
v a l ( i , j ) = ( l o c j − l o c i ) × ( ∑ 1 i − 1 a [ i ] + ∑ j + 1 n a [ i ] ) val(i,j)=(loc_j-loc_i)\times (\sum_{1}^{i-1}a[i]+\sum_{j+1}^{n}a[i]) val(i,j)=(locjloci)×(1i1a[i]+j+1na[i])


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
#define val(l,r,L,R) (loc[r]-loc[l])*(s[L]+s[n]-s[R-1])
using namespace std;
inline signed iut(){
    rr int ans=0,f=1; rr char c=getchar();
    while (!isdigit(c)) f=(c==45)?-f:f,c=getchar();
    while (isdigit(c)) ans=ans*10+(c-48),c=getchar();
    return ans;
}
int n=iut(),c=iut(),loc[51],s[51],dp[51][51][2];
inline signed min(int a,int b){return a<b?a:b;}
signed main(){
    memset(dp,127/3,sizeof(dp));
    for (rr int i=1;i<=n;++i){
        rr int a=iut(),b=iut();
        loc[i]=a,s[i]=s[i-1]+b;
    }
    dp[c][c][0]=dp[c][c][1]=0;
    for (rr int j=c;j<=n;++j)
    for (rr int i=j-1;i;--i)
        dp[i][j][0]=min(dp[i+1][j][0]+val(i,i+1,i,j+1),dp[i+1][j][1]+val(i,j,i,j+1)),
        dp[i][j][1]=min(dp[i][j-1][0]+val(i,j,i-1,j),dp[i][j-1][1]+val(j-1,j,i-1,j));
    printf("%d",min(dp[1][n][0],dp[1][n][1]));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值