【动态规划】Coin Change 2硬币问题(2)

原创 2018年04月16日 09:28:06

Description
有n种硬币,面值分别为V1,V2,V3,…..Vn,每种都有无限多。
给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?
输出硬币数目的最小值和最大值。1<=n<=100, 0<=S<=10000,1<=Vi<=S。

Input Data
输入有三行:第一行一个整数S;第二行一个整数n,表示硬币种数;第三行n个整数,表示硬币面值

Output Data
输出四行:前两行为最小值,和组成最小值的方案;后两行为最大值和方案。若有多种方案,输出字典序最小的(即序号尽量小的),方案中之只包含面值的序号。

Input / Output Sample
6
4
3 1 2 5
Output Sample
2
1 1
6
2 2 2 2 2 2

————————————————分割の线————————————————
分析
这是一道dp的入门好题。显然是一种无限背包的变形题(将最大和最小相融合),除此之外还要注意opt的记录。
对于背包不熟悉的,可以尝试一下[luoguP1060]开心的金明

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,s;
int v[200];//不同硬币的面值
int f[10010],opt[10010][2];
//f[i]表示距离目标面值差i的方案数
//opt[i][0]表示从转移到i点前原始状态,opt[i][1]表示转移时使用的硬币的序号
void write(int x)
{
    if(opt[x][0]!=s) //如果当前状态不为初始状态时,再次通过opt进行回溯
    {
        printf("%d ",opt[x][1]);
        write(opt[x][0]);
        return ;
    }
    else printf("%d",opt[x][1]);//注意省略文末空格
    return ;
}
int main()
{
    cin>>s>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&v[i]);
    memset(f,-1,sizeof(f));//将除初始状态之外的其他状态,全标记为未赋值(-1)
    memset(opt,0,sizeof(opt));//其实是不需要的
    f[s]=0;
    for(int i=n;i>=1;i--)//从后往前枚举,注意取的是≥(>=),如此可以有效更新字典序比它大的原始序列。想一下这是为什么?
        for(int j=s;j>=v[i];j--)//注意是无限背包问题
        {
            if(f[j]!=-1)
                if(f[j-v[i]]==-1||f[j-v[i]]>=f[j]+1)//刷表法,从当前状态出发更新f[j-v[i]]的值
                {
                    opt[j-v[i]][0]=j,opt[j-v[i]][1]=i;
                    f[j-v[i]]=f[j]+1;
                }
        }
    printf("%d\n",f[0]);//输出方案数
    write(0);//回溯输出使用硬币的序列
    cout<<endl;
    //如下同上
    memset(f,-1,sizeof(f));
    memset(opt,0,sizeof(opt));
    f[s]=0;
    for(int i=n;i>=1;i--)
        for(int j=s;j>=v[i];j--)
        {
            if(f[j]!=-1)
                if(f[j-v[i]]==-1||f[j-v[i]]<=f[j]+1)
                {
                    opt[j-v[i]][0]=j,opt[j-v[i]][1]=i;
                    f[j-v[i]]=f[j]+1;
                }
        }
    printf("%d\n",f[0]);
    write(0);
    cout<<endl;
    return 0;
}
版权声明:写得不好,随便转载,但请注明出处,感激不尽 https://blog.csdn.net/xyc1719/article/details/79956310

任意位置显示html菜单

脚本说明:把如下代码加入区域中document.onclick = popUp   function popUp() {newX = window.event.x + document.body.sc...
  • denal
  • denal
  • 2003-03-10 10:21:00
  • 867

Coin Change

You are given coins of different denominations and a total amount of money amount. Write a functio...
  • brucehb
  • brucehb
  • 2016-02-19 00:30:55
  • 310

LeetCode.322(518) Coin Change && Coin Change2

题目322:You are given coins of different denominations and a total amount of money amount. Write a fun...
  • xiakexiaohu
  • xiakexiaohu
  • 2017-12-02 22:01:10
  • 31

Coin ChangeAC代码递归+详细、人道的注释

Coin ChangeTime Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...
  • qq_36696004
  • qq_36696004
  • 2018-02-27 22:26:39
  • 17

leetcode 322. Coin Change-硬币交换|动态规划

原题链接:322. Coin Change 【思路】 本题考查动态规划。也许一开始很容易想到用贪心算法,但是贪心算法在某些情况下是不成立的,比如coins = [1, 3, 5, 6],要amount...
  • happyaaaaaaaaaaa
  • happyaaaaaaaaaaa
  • 2016-03-24 23:19:37
  • 6244

UVA 674 Coin Change 换硬币 经典dp入门题

题意:有1,5,10,25,50五种硬币,给出一个数字,问又几种凑钱的方式能凑出这个数。 经典的dp题。。。可以递推也可以记忆化搜索。。。 我个人比较喜欢记忆化搜索,递推不是很熟练。 记...
  • hcbbt
  • hcbbt
  • 2013-09-21 10:09:19
  • 7496

Coin Change 2-硬币问题

Coin Change 2 Add to List You are given coins of different denominations and a total amount of mone...
  • Sunny_Ran
  • Sunny_Ran
  • 2017-03-07 23:03:01
  • 880

[leetcode] 518. Coin Change 2 -- JavaScript 代码【动态规划】

var change = function(amount, coins) { var dpArray = []; for(let i=0;i
  • u014328357
  • u014328357
  • 2017-03-30 10:48:21
  • 556

leetcode 518. Coin Change 2 类似背包问题 + 很简单的动态规划DP解决

You are given coins of different denominations and a total amount of money. Write a function to comp...
  • JackZhang_123
  • JackZhang_123
  • 2017-12-16 16:28:54
  • 89

动态规划之硬币兑换(Coin Change)

原文地址:Dynamic Programming | Set 7 (Coin Change)已知N,如果我们想要换N分,而且每种S = { S1, S2, .. , Sm} 价值的硬币是不限数量的,那...
  • sinat_36246371
  • sinat_36246371
  • 2016-10-17 10:22:50
  • 356
收藏助手
不良信息举报
您举报文章:【动态规划】Coin Change 2硬币问题(2)
举报原因:
原因补充:

(最多只允许输入30个字)