题目:
有n种硬币,面值分别为V1,V2,...Vn,每种都有无限多。给定非负整数S,可以选用多少个硬币,使得面值之和恰好为S?输出硬币数目的最小值和最大值!
分析:我们把每种面值看作一个点!表示“还需要凑足的面值”,初始状态为S,目标状态为0。那么若当前状态在i,每使用一个硬币j,状态便转移到i-Vj
因为求最大值跟求最小值类似,这里只贴记忆化搜索求最小值代码
代码: 下面dp1跟dp2功能相同。
不同dp2好理解一些。通过设置数组vis,标识是否访问过。牺牲空间换取效率,易读性。
<span style="font-size:24px;">#include"stdio.h"
#include"stdlib.h"
#include"algorithm"
#include"string.h"
#include"math.h"
using namespace std;
const int INF=1e9;
const int max_coin=105;
const int max_S=10005;
int coin[max_coin];
int d[max_S];
int vis[max_S];
int n;
//d(i) 从节点i出发到节点0的最长路径
int dp1(int S)
{
//if(S==0) return 0;
int &ans=d[S];
if(ans!=-1) return ans; //记忆化搜索
ans=INF;
for(int i=0;i<n;i++)
{
if(S>=coin[i])
ans=min(ans,dp1(S-coin[i])+1);
}
ans=ans&#