(dp入门)换硬币

有2元的 5元的 7元的 硬币若干,凑出27元,需要最小硬币数

这是一个动态规划问题,对动态规划求解的思路如下:

 

 

1.确定状态:确定最后一步和倒数第二步之间的关系,就是把后面的问题转化为前面的子问题

x可以由x-2的情况再选面值2的硬币得到,也可以由x-5的情况选5面值的得到,还可以由x-7由面值7的得到

2.根据状态写出转移方程

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

3.确定初始条件和边界情况

初始条件dp[0]=0

数组不能越界,考虑i-2和i-5和i-7的越界情况

#include<iostream>
#include<string.h>
#include<math.h>

using namespace std;
int n,m,k; 
int ans;
int mod=1e9+7;
int a[105];
bool vis[105]; 

int main(){
    cin>>n;
    memset(a,999999,sizeof(a));
    a[0]=0;
    for(int i=1;i<=n;i++){
        if(i>=2){
            a[i]=min(a[i],a[i-2]+1);
        }
        if(i>=5){
            a[i]=min(a[i],a[i-5]+1);
        }
        if(i>=7){
            a[i]=min(a[i],a[i-7]+1);
        }
    }
    cout<<a[n];
    return 0;
}

更一般的,告诉m种硬币的值每种值bi,求凑够n需要最小硬币数

#include<iostream>
#include<string.h>
#include<math.h>

using namespace std;
int n,m,k; 
int ans;
int mod=1e9+7;
int dp[105],b[105];
bool vis[105]; 

int main(){
    cin>>n>>m;                                // n:换的总钱价值  m:硬币总数 
    for(int i=0;i<m;i++){
        cin>>b[i];                            // 每种硬币的价值 
    }
    memset(dp,999999,sizeof(dp));             //初始化设置dp较大值 便于后面更新 
    dp[0]=0;                                  //初始条件 dp[0]=0 
    for(int i=1;i<=n;i++){                    //到 i 需要换的硬币最小个数 
        for(int j=0;j<m;j++){                 //依此考虑到 i 后每种硬币可能的换的最小个数  
            if(i>=b[j]){
                dp[i]=min(dp[i],dp[i-b[j]]+1);
            }
        }
    }
    cout<<dp[n];
    return 0;
}

 

posted @ 2020-03-13 23:52  Maxwell·  阅读(363)  评论(0编辑  收藏  举报