暑假学习-dp的硬币问题

利用动态规划解决面值为1, 5, 10, 25, 50的硬币找零问题,最小化硬币数量。公式为m[i]=min{m[i], m[i-t[j]]+1}。若需输出组合,需记录最后一枚硬币并回溯;若求所有组合,dp式子改为dp[i]+=dp[i-t[j]]。" 102682878,8103159,KGB知识图谱在大数据时代的优势,"['知识图谱', '大数据处理', '文本分析', '知识工程']
摘要由CSDN通过智能技术生成

你有面值为1 5 10 25 50的硬币,给定金钱n要求换的的硬币数最少,问最少的硬币的数目是多少。
比较简单就直接写式子了,dp的式子为 m【i】=min{m【i】,m[i-t[j]]+1}
代码为

#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
const int N=100005;
typedef long long ll ;
int date[N];
#define swap(a,b) {int t=a;a=b;b=t;}
const int mn=251;
const int va=5;
int t[va]={1,5,10,25,50};
int m[mn];
void so()
{
    for(int k=0;k<mn;k++)
        m[k]=99999;
    m[0]=0;
    for(int j=0;j<va;j++)
        for(int i=t[j];i<mn;i++)
        m[i]=min(m[i],m[i-t[j]]+1);
}
int main()
{
    int s;
    so();
    while(cin>>s)
    {
        cout<<m[s]<<endl;
    }
    return 0;
}

如果还要输出最后硬币的组合情况,则需要把最后一枚硬币记录下来,然后向前找即可。

#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
const int N=100005;
typedef long long ll ;
int date[N];
#define swap(a,b) {int t=a;a=b;b=t;}
const int mn=251;
const int va=5;
int t[va]={1,5,10,25,50};
int m[mn];
int mp[mn]={0};
void so()
{
    for(int k=0;k<mn;k++)
        m[k]=99999;
    m[0]=0;
    for(int j=0;j<va;j++)
        for(int i=t[j];i<mn;i++)
    {
        if(m[i]>m[i-t[j]]+1)
        {
            mp[i]=t[j];
            m[i]=m[i-t[j]]+1;
        }
    }

}
void ans(int *mp,int s)
{
    while(s)
    {
        cout<<mp[s]<<" ";
        s=s-mp[s];
    }

}
int main()
{
    int s;
    so();
    while(cin>>s)
    {

        cout<<m[s]<<endl;
        ans(mp,s);

    }
    return 0;
}

若是求所有的组合
把dp式子改为dp[i]+=dp[i-t[j]] 即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值