专栏文章

B3873 [GESP202309 六级] 小杨买饮料 题解

B3873题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mipcmoca
此快照首次捕获于
2025/12/03 09:49
3 个月前
此快照最后确认于
2025/12/03 09:49
3 个月前
查看原文

题意大意

NN 种饮料,第 ii 种饮料价值 cic_i 花费 lil_i,求在每种饮料只买一种且总花费大等于 LL 的情况下最小价值。

题目思路

这道题可以用动态规划的刷表法写。
刷表法:由当前点的状态,更新其他点的状态。
需要注意:只用当每个状态所依赖的状态对它的影响相互独立。

代码实现

fi,jf_{i,j} 代表买 ii 种饮料,总容量为 jj 毫升的最小花费。但是题目说总容量大于等于 LL 即可,所以我们要将 j+li+1j+l_{i+1} 大于等于 LL 的情况存 fi+1,Lf_{i+1,L}。则我们可以双重循环实现买或不买。
买的话,先判断 j+li+1j+l_{i+1} 是否大于 LL。如果小于 LL 就将 fi+1,j+li+1f_{i+1,j+l_{i+1}} 设为买第 i+1i+1 个的情况和原来的 fi+1,j+li+1f_{i+1,j+l_{i+1}} 值之间的最小值。否则就把它们之间的最小值存到 fi+1,Lf_{i+1,L}。不买的话,将 fi+1,jf_{i+1,j} 设为 fi,jf_{i,j}fi,jf_{i,j} 之间的最小值。 最后判断 fN,Lf_{N,L} 是否被修改,进行输出。

代码

CPP
//码风不好,请见谅
#include <bits/stdc++.h>
using namespace std;
int f[510][2010],c[510],l[510];
int main() {
    int N,L;cin>>N>>L;
    for(int i=1;i<=N;i++) cin>>c[i]>>l[i];
    memset(f,0x3f,sizeof(f));f[0][0]=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<=L;j++){
            //刷表法
            if(j+l[i+1]<L){
                f[i+1][j+l[i+1]]=min(f[i][j]+c[i+1],f[i+1][j+l[i+1]]);//买
            }else{
                f[i+1][L]=min(f[i][j]+c[i+1],f[i+1][L]);//买
            }
            f[i+1][j]=min(f[i+1][j],f[i][j]);//不买
        }
    }
    if(f[N][L]>=1e9){//判断值是否被修改
        cout<<"no solution";
    }else{
        cout<<f[N][L];
    }
    return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...