题目描述
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。
输入描述:
输入包括两行,第一行两个整数n(0<=n<=1000)代表数组长度和aim(0<=aim<=5000),第二行n个不重复的正整数,代表arr
输出描述:
输出一个整数,表示组成aim的最小货币数,无解时输出-1.
示例1
输入
3 20
5 2 3
输出
4
解法一:暴力递归
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] info = br.readLine().trim().split(" ");
int len = Integer.parseInt(info[0]);
int aim = Integer.parseInt(info[1]);
String[] ss = br.readLine().trim().split(" ");
int[] arr = new int[len];
for(int i=0;i<len;i++){
arr[i] = Integer.parseInt(ss[i]);
}
int res = findMin(arr,aim);
System.out.println(res);
}
public static int findMin(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0) return -1;
return process(arr,0,aim);
}
public static int process(int[] arr,int i,int rest){
if(i==arr.length){
return rest==0?0:-1;
}
int res = -1;
for(int k=0;k*arr[i]<=rest;k++){
int next = process(arr,i+1,rest-k*arr[i]);
if(next!=-1){
res = res==-1?next+k:Math.min(next+k,res);
}
}
return res;
}
}
解法二:动态规划
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] info = br.readLine().trim().split(" ");
int len = Integer.parseInt(info[0]);
int aim = Integer.parseInt(info[1]);
String[] ss = br.readLine().trim().split(" ");
int[] arr = new int[len];
for(int i=0;i<len;i++){
arr[i] = Integer.parseInt(ss[i]);
}
int res = findMin(arr,aim);
System.out.println(res);
}
public static int findMin(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0) return -1;
if(aim==0) return 0;
int N = arr.length;
int[][] dp = new int[N+1][aim+1];
for(int i=1;i<=aim;i++){
dp[N][i] = -1;
}
for(int i=N-1;i>=0;i--){
for(int j=1;j<=aim;j++){
if(j-arr[i]>=0){
if(dp[i+1][j]!=-1&&dp[i][j-arr[i]]!=-1){
dp[i][j] = Math.min(dp[i][j-arr[i]]+1,dp[i+1][j]);
}else if(dp[i+1][j]!=-1){
dp[i][j] = dp[i+1][j];
}else if(dp[i][j-arr[i]]!=-1){
dp[i][j] = dp[i][j-arr[i]]+1;
}else{
dp[i][j] = -1;
}
}else{
dp[i][j] = dp[i+1][j];
}
}
}
return dp[0][aim];
}
//用来参考套模板
public static int process(int[] arr,int i,int rest){
if(i==arr.length){
return rest==0?0:-1;
}
int res = -1;
for(int k=0;k*arr[i]<=rest;k++){
int next = process(arr,i+1,rest-k*arr[i]);
if(next!=-1){
res = res==-1?next+k:Math.min(next+k,res);
}
}
return res;
}
}