硬币问题

问题描述:

有n种硬币,币值分别是V1 ..... Vn,每种都有无限多。给定给负整数S,可以选用多少个硬币,使得面值之和恰为S。输出硬币数目的最小值和最大值。

1 <= n <= 100, 0 <= s <= 10000

题目分析:

本题可以看作是DAG上的路径问题,起点为S,重点为0,设d[ i ] 为从i出发的路径长度

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string.h>
#define inf 0x3f3f3f3f
using namespace std;
int sum;
int n;
int b[100];//储存币值 
int d_max[10000];
int d_min[10000];
bool v[100];
void dp1(){
    for(int i=1; i <= sum; i++){
        for(int j = 0; j < n; j++){
            if(b[j] <= i){
                d_max[i] = max(d_max[i], d_max[i-b[j]]+1);
                d_min[i] = min(d_min[i], d_min[i-b[j]]+1);
            }
        }
    }
} //循环递推 
int dp2(int i){
    if(v[i] == 1)
        return d_max[i];
    for(int j=0;j<n;j++)
        if(b[j] <= i)
             d_max[i] = max(d_max[i], dp2(i-b[j])+1);
    v[i] == 1;
    return d_max[i];
}
int main(){
    scanf("%d",&n);
    for(int i = 0; i < n; i++)
        scanf("%d",&b[i]);
    scanf("%d",&sum);
    memset(d_max,-inf,sizeof(int)*(sum+1));
    memset(d_min,inf,sizeof(int)*(sum+1));
    memset(v,0,sizeof(v));
    d_min[0] = 0;
    d_max[0] = 0;
    //dp1();
    dp2(sum);
    //cout<<d_min[sum]<<endl;
    cout<<d_max[sum]<<endl;
    return 0;
}

 

posted @ 2019-02-01 15:38  阳离子  阅读(297)  评论(0编辑  收藏  举报