硬币问题
问题描述:
有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; }