问题描述:
有n种硬币,面值分别为v1,v2,v3...vn,每种硬币有无限多,给定非负整数s,可以选用多少个硬币,使得面值之和恰好为s?输出硬币数目的最小值和最大值,并且输出各自的选取方案(如果有多种方案,则输出硬币编号字典序较小的方案,输出每种选取方案的面值)。
分析:本质上市一个DAG上的路径问题,我们把每种面值看做一个点,表示还需凑足的面值,则初始状态为0,目标状态为0,若当前在i,则每使用一枚硬币j,状态转移到i-vj。
代码:
#include<stdio.h>
#define N 1100
int v[N],min[N],max[N],min_coins[N],max_coins[N];
void print_ans(int *d,int s, int n) {
while(s){
printf("%d ",v[d[s]]);
s-=v[d[s]];
}
printf("\n");
}
int main() {
int T,i,j,n,s;
scanf("%d",&T);
while(T--) {
scanf("%d %d",&n,&s);
for(i=0;i<n;i++)
scanf("%d",&v[i]);
min[0]=max[0]=0;
for(i=1;i<=s;i++){
min[i]=0x7FFFFFFF;
max[i]=-0x7FFFFFFF;
}
for(i=1;i<=s;i++){