题目:有n种硬币,面值分别为V1,V2,...Vn,每种都有无限多。给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?输出硬币数目的最小值!
状态:d[i] 表示i 元最少要换多少个硬币,那么我们便要求d[S}的值;
状态如何转移:i元换零钱V[j](i>=V[j]),后状态变为 d[i-V[j]];
状态选取:选d[j]的值最小的,这样d[S]才会最小,所以d[i]=min{d[i-V[j]],(j为1~n);
1)记忆搜索法:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int d[5000];
int v[4]={0,3,5,7};
int S,n=3;
const int INF=1<<7-1;
/* 递归法 */
int dp(int S) //ans=-1表示未计算;
{ //ans=0表示到终点;
int& ans=d[S]; //ans=-(1<<30)表示走不通;
if(ans != -1) return ans; //也可以用vis[N]数组保存,表示是否计算过;
ans=(1<<30);
for(int i=1;i<=n;i++)
if(S>=v[i]) ans=min(ans,dp(S-v[i])+1);
return ans;
}
void prin