首页 > 其他分享 >题解:CF687C The Values You Can Make

题解:CF687C The Values You Can Make

时间:2024-08-01 13:28:08浏览次数:6  
标签:硬币 int 题解 Make 凑出 Values 集合 价值 dp

CF687C The Values You Can Make 题解

题目翻译感觉不明不白的(至少我看了几遍没看懂),这里给个较为清晰的题面。

题目描述

给你 \(n\) 个硬币,第 \(i\) 个硬币有一个价值 \(c_i\),你需要从中选出一些价值和为 \(k\) 的硬币组成一个集合,再输出这个集合中硬币可能组成的价值和。

算法

动态规划,背包。

分析

看完我给的题面描述其实已经很清晰了。这道题可以分为两步:

  • 从 \(n\) 个硬币中选出来价值和为 \(k\) 的硬币集合。
  • 输出硬币集合所能凑出的价值和。

我们很容易发现如果是任意一个步骤都很好做,用 \(01\) 背包解决。看数据范围 \(n\le 500\),考虑套两个 \(01\) 背包。

现在设计状态。我们发现对于每个硬币,它都有三种处理可能:不选入硬币集合,选入硬币集合但不用来凑价值和,选入硬币集合且用来凑价值和。所以我们设 \(dp[i][j][k]\) 表示前 \(i\) 个硬币中选出价值和为 \(j\) 的硬币集合,用来凑出价值和 \(k\) 是否可行。

状态转移方程就很好推了,对于前一个硬币有上述三种处理可能,只要有一种可行那么这个硬币就可行,转移方程为 \(dp_{i,j,k}=dp_{i-1,j,k}|dp_{i-1,j-c_i,k}|dp_{i-1,j-c_i,k-c_i}\)。分别对应三种处理可能。

注意一下边界 \(dp_{0,0,0}=1\),最终遍历一遍 \(dp_{n,k,p}(0\le p\le 500)\),如果为真就说明可以凑出输出即可,复杂度 \(\mathcal O(n^3)\)。

注意一下直接开三维数组会 MLE,需要用滚动数组优化,这里不细说了,和 \(01\) 背包一样。

代码

码风较丑,不喜勿喷。(@jiayixuan1205 的好看去看她的

#include<bits/stdc++.h>
using namespace std;
namespace Ryan
{
    const int N=500,M=505;
    int dp[M][M],c[M];
    int n,kk;
    signed work()
    {
        cin>>n>>kk;
        for(int i=1;i<=n;i++)
            cin>>c[i];
        dp[0][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=N;j>=0;j--)
                for (int k=N;k>=0;k--)
                    if(j>=c[i])
                    {
                        dp[j][k]|=dp[j-c[i]][k];
                        if(k>=c[i])
                            dp[j][k]|=dp[j-c[i]][k-c[i]];
                    }
        int ans=0;
        for(int i=0;i<=N;i++)
            if(dp[kk][i])ans++;
        cout<<ans<<endl;
        for(int i=0;i<=N;i++)
            if(dp[kk][i])
                cout<<i<<" ";
        return 0;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return Ryan::work();
}

标签:硬币,int,题解,Make,凑出,Values,集合,价值,dp
From: https://www.cnblogs.com/RyanAdam/p/18336484

相关文章

  • 题解:CF559B Equivalent Strings
    CF559BEquivalentStrings题解题目描述吐槽一下,题目翻译有歧义。思路分析你会发现,当你需要判断字符串\(a,b\)是否等价时,如果长度为偶数,需要继续判断字符串\(a\)拆分的字串。所用知识s.substr(i,j)//在字符串s中,从位置i开始截取长度为j的字串参考代码#include<bits......
  • 分享LVGL v9移植到imx6ull的过程(CMake)
    最近在做一个用cmake构建的项目需要用到LVGL,但是找资料的时候发现很少有分享v9的移植,自己移植也踩了很多坑所以决定分享一下移植过程。1.LVGL获取gitclonehttps://github.com/lvgl/lv_port_linux.gitgit之后发现这个包的lvgl文件夹里面是空的gitclonehttps://github.......
  • 题解:CF718A Efim and Strange Grade
    CF718AEfimandStrangeGrade题解算法贪心+模拟思路分析显然,要最优每一次进位就只能五入不能四舍。而且当我们五入时,要取位数最高的。比如说\(1.3535\),我们有两种进位方式,一种是进位成\(1.4\),一种是进位成\(1.354\),显然前者更优。那这道题给的次数有啥用呢?考虑一种“......
  • P10511 方差 题解
    【题目简述】定义一个长度为\(n\)的序列\(a\)的方差为:\(s^2=\frac{1}{n}\sum_{i=1}^n(a_i-\overline{a})^2\)。\(\sum\)为累加求和符号,\(\overline{a}\)为序列\(a\)的平均数。给定\(m\)个形如\([l,r,b]\)的组合,表示\(a_l,a_{l+1},\ldots,a_r\)为\(b\)。给定......
  • 洛谷P2696之慈善的约瑟夫——题解
    洛谷P2696题解[传送锚点](P2696慈善的约瑟夫-洛谷|计算机科学教育新生态(luogu.com.cn))比不过大佬,从蒟蒻做起选择比较水有意思的解法——用队列模拟(还是窝太弱了)正片开始考虑队列模拟,因为每次都是假的剔除,所以我们的目标是找到每回游戏的最终存活者。将不被剔除,......
  • 题解:Pinely Round 4 (Div. 1 + Div. 2) C
    C.AbsoluteZerotimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputYouaregivenanarray\(a\)of\(n\)integers.Inoneoperation,youwillperformthefollowingtwo-stepmove:Choose......
  • CMAKE 《window构建项目》
    安装参考链接https://subingwen.cn/https://subingwen.cn/cmake/CMake-primer/cmakehttps://cmake.org/download/下载根据需求安装合适的版本mingw64https://www.mingw-w64.org/下载根据需求安装合适的版本https://sourceforge.net/projects/mingw-w64/files/mi......
  • Codeforces 11D A Simple Task 题解 [ 蓝 ] [ 状压 dp ]
    思路不难想,细节比较多。思路观察到\(n\le19\),首先想到状压dp。于是自然地定义\(dp[j][i]\)为:抵达点的状态为\(i\),且此时在点\(j\)时,简单路径的条数。注意这里是简单路径的条数,而不是环的个数,因为环的个数要在dp过程中统计。这里的dp作用就在于求简单路径条数。......
  • [JOI 2020 Final] 火事 题解
    给一篇题解。(下面这张图是从luogu上粘贴的,因为不太会画图)其中纵坐标为\(t\),横坐标为\(a_i\)。发现同颜色块只有平行四边形和直角梯形(等腰直角三角形)两种情况。可以将直角梯形削去左下角,分成两部分考虑。等直可以直接暴力插入区间,总个数\(O(n)\)。平行四边形可以看作上......
  • [CF455D] Serega and Fun 题解
    不知道大家做没做过数列分块基础9题?插入删除操作可以用链表,线段树等数据结构都不好维护,考虑分块。对于修改操作,暴力重构受影响块的链表,发现除首尾块外,其他块都可以看作是区间左移一位,所以加头删尾即可。每个块开一个数组(绝对不能是\((un\_)map\),不然你会和我一样死的很诡异),表示......