【csp202209-2】何以包邮?

一开始不知道这种方法,但当时大致思路和这个很像,自己做的时候只有25。第一次的方法问题在于:

比如说10 20 30 40 50 60 70,我可以算得10+20+30,算不得10+20+40,即我不能选择在买了两本以上的书之后,其它的书如果买会怎样,如果不买会怎样,少考虑了很多种可能。

第二次查阅资料,学会下面这种做法,25->70☑️

思路就是求出所有可能,遇到满足条件的就检查是否需要更新结果。dfs的核心就是,如果选这本书,则检查是否不小于x,是,则和已有的最小值比较,否,则接下去考虑是否选下一本书。如果不选这本书,接下去考虑是否选下一本书。

#include<iostream>
#include<algorithm>
using namespace std;
int m=1000010;
void dfs(int nownum,int s,int a[],int n,int x){
    if(m==x){return;}
    for(int i=nownum;i<n;++i){
        if(s+a[i]>=x){
            m=min(s+a[i],m);
        }
        else{
            dfs(i+1,s+a[i],a,n,x);
        }
    }
    return;
}
int main(){
    int n,x;
    cin>>n>>x;
    int a[n];
    for(int i=0;i<n;++i){
        cin>>a[i];
    }
    dfs(0,0,a,n,x);
    cout<<m;
}

但是有没有可能,即使选了剩下全部的书也不能达到x?这个时候就不需要考虑了。基于这个,我们可以对现有dfs算法进行修改。(因为时隔几天才重做的,对dfs理解得更透彻一点,所以这次dfs表达方式也不一样了)

剩下的书的总价可以用前缀和计算,之前有详细介绍前缀和,这里要求的相当于是一个大线段减去小线段,剩下的书的总价即为剩下的线段。

老规矩,如果已经到边界,就结束函数;如果剩下的所有书都买还凑不够包邮,也结束函数;剩下两种情况和第一次写的dfs一样。

#include<iostream>
#include<algorithm>
using namespace std;
int book[31];
int sum[32]={0};
int minmoney=300010;
void dfs(int now,int s,int n,int x){
    if(now==n){return;}
    if(s+sum[n]-sum[now]<x){return;}
    if(s+book[now]>=x){
        minmoney=min(minmoney,book[now]+s);
    }
    else{dfs(now+1,s+book[now],n,x);}
    dfs(now+1,s,n,x);
}
int main(){
    int n,x;
    cin>>n>>x;
    for(int i=0;i<n;++i){
        cin>>book[i];
        sum[i+1]=sum[i]+book[i];
    }
    dfs(0,0,n,x);
    cout<<minmoney;
}

第三次再查阅资料,看到了这种方法。

同样是记录下所有可能,判断某个总价值是否有组合能实现,如果有,则该总价值是存在的。本质上呢还是背包问题,水平地走遍一个数的所有可能。如果说dfs是纵深的,它就是水平方向的。

利用数组下标代表总价值,最后从下标为x(包邮线)开始遍历,第一个价值存在的下标则为最低价格。

#include<iostream>
using namespace std;
int s[300010]={0};
int main(){
    int n,x;
    cin>>n>>x;
    s[0]=1;
    for(int i=0;i<n;++i){
        int tempnum;
        cin>>tempnum;
        for(int j=300009;j>=tempnum;--j){
            if(j-tempnum>=0 and s[j-tempnum]==1){
                s[j]=1;
            }
        }
    }
    for(int i=x;i<=300009;++i){
        if(s[i]==1){
            cout<<i;
            break;
        }
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目编号为202209-2的题目是《何以包邮?》。这道题的问题描述是关于购物车中的图书数量和包邮最低值的计算。其中提供了两种解题方法,一种是直接无脑解,另一种是满分题解。[3] 直接无脑解的方法是通过输入购物车中的图书数量n和包邮最低值x,然后设置一个列表a来存储每本书的价格。接着进行遍历,将每本书的价格依次存入列表a,并对列表a进行从低到高的排序。在遍历过程中,判断是否小于最小的包邮值,如果是,则将该价格添加到集合temp中。最后,从集合temp中选择一个最小的价格作为答案输出。 满分题解的方法是在直接无脑解的基础上使用了动态规划的思想。同样是输入购物车中的图书数量n和包邮最低值x,然后设置一个列表a来存储每本书的价格。接着,设置一个动态规划数组dp来存储每个价格的最小花费。在遍历过程中,将每本书的价格依次存入列表a,并设置一个变量pre来保存目前满足包邮的最小花费。然后使用01背包解法,将每个地方的最优解存入dp数组中。最后,从包邮最低值x开始遍历,找到超过x的dp[i]并输出。 综上所述,题目编号为202209-2的题目《何以包邮?》是关于购物车中图书数量和包邮最低值的计算问题,提供了直接无脑解和满分题解两种解题方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [CCF-CSP真题《202209-2 何以包邮?》思路+python满分题解](https://blog.csdn.net/weixin_53919192/article/details/127173638)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值