DP(1):最值型

题目:

输入有的硬币种类,求凑出指定数的最少硬币数量.
如:有2分,5分,7分的硬币,要凑出27元所需的最少硬币数量.
视频解析参考

解析:

一.确定状态

①最后一步

  • 最优策略一定是k个硬币面值加起来是27
  • 一定有最后一个硬币ak
  • 除掉这个硬币,前面的硬币加起来是27-ak
  • 27-ak的硬币数是最少的,是最优的

②子问题

  • 最少用多少硬币可以拼出27-ak
  • 原问题是最少用多少硬币拼出27
  • 状态: f(x)=最少用多少硬币拼出x
  • 最后那个硬币的ak值是多少未知,但是只有3中可能的值

二.转移方程

f[i] = min(f[i-2]+1,f[i-5]+1,f[i-7]+1)

三.初始条件和边界条件

①初始条件: f[0]=0(用转移方程计算不出来的,但是我们又需要它的定义)
②边界条件: 如果不能拼出y,就定义为正无穷

四.计算顺序

从小到大.当计算到f[x]时,f[x-2],f[x-5],f[x-7]都已经得到结果了.

solution:

#include <iostream>
#include <vector>
#define MAX 27
const int inf = (int) 1e9+7;
using namespace std;
int main()
{

    int D[MAX+1];//D[i]表示拼出i元需要的最少硬币数量
    D[0] = 0;
    //输入指定的硬币值
    vector<int> vec;
    int k;
    while(cin>>k)
    {
        vec.push_back(k);
        if(cin.get()=='\n')
           break;
    }
    int n = vec.size();
    int i,j;
    //D[1],D[2]...
    for(i = 1;i<=27;i++)//拼出i元
       {
           D[i] = inf;//初值都设置为无穷大
           //最后一步
           for(j=0;j<n;j++)//有n中硬币;试最后一枚硬币是多大;每一步尝试3种硬币
           {
               if(i>=vec[j] && D[i-vec[j]]!=inf)
                  D[i] = min(D[i-vec[j]]+1,D[i]);//保证求当前值的时候用到的值都已经求解出来了
           }
       }
       if(D[27] == inf) D[27] = -1;
          cout<< D[27]<<endl;
          return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值