动态规划并使用空间压缩
O(n*aim)
O(aim)
import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Main { public static Scanner sc = new Scanner(System.in); public static void main(String[] args) { int n = sc.nextInt(); int aim = sc.nextInt(); int[] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = sc.nextInt(); } if(aim < 0){ System.out.print(-1); return; } int maxVal = Integer.MAX_VALUE; /** * dp[i][j],arr[0...i]换取钱数为j的最小数目 * dp[][0] = 0, 换取钱数为0的数目都设置成0;若换取钱数换不到可以设成 Integer.MAX_VALUE * 二维空间压缩 */ int[] dp = new int[aim+1]; dp[0] = 0; for(int j =1;j<=aim;j++){ dp[j] = maxVal; } int val = arr[0]; int cnt = 1; while (val <= aim){ dp[val] = cnt; cnt++; val = cnt * arr[0]; } // 动归 for(int i=1;i<n;i++){ // 完全不使用 arr[i] // 到使用1张 arr[i] // 使用2张 arr[i] // ... // 使用 aim / arr[i] 张 for(int j=1;j<=aim;j++) { int tmpDpJ = maxVal; int cntMax = j / arr[i]; for (int k = 0; k <= cntMax; k++) { int tmp = dp[j - k * arr[i]] + k; if(tmp >= 0 && tmp <= tmpDpJ) { tmpDpJ = tmp; } } dp[j] = tmpDpJ; } } if(dp[aim] == Integer.MAX_VALUE) { System.out.println(-1); }else { System.out.println(dp[aim]); } } }
import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Main { public static Scanner sc = new Scanner(System.in); /* 3 20 5 2 3 4 2 2 3 5 -1 */ public static void main(String[] args) { int n = sc.nextInt(); int aim = sc.nextInt(); int[] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = sc.nextInt(); } int maxVal = Integer.MAX_VALUE; /** * dp[i][j],arr[0...i]换取钱数为j的最小数目 * dp[][0] = 0, 换取钱数为0的数目都设置成0;若换取钱数换不到可以设成 Integer.MAX_VALUE */ int[][] dp = new int[n][aim+1]; // j = 0 都设置为0 for(int i = 0; i < n; i++){ dp[i][0] = 0; } // 只使用第一张 // 处理dp[0][1...aim] for(int j =1;j<=aim;j++){ dp[0][j] = maxVal; } int val = arr[0]; int cnt = 1; while (val <= aim){ dp[0][val] = cnt; cnt++; val = cnt * arr[0]; } // 动归 for(int i=1;i<n;i++){ // 完全不使用 arr[i] // 到使用1张 arr[i] // 使用2张 arr[i] // ... // 使用 aim / arr[i] 张 for(int j=1;j<=aim;j++) { dp[i][j] = maxVal; int cntMax = j / arr[i]; for (int k = 0; k <= cntMax; k++) { int tmp = dp[i - 1][j - k * arr[i]] + k; if(tmp >=0 && tmp <= dp[i][j]) { dp[i][j] = tmp; } } } } if(dp[n-1][aim] == Integer.MAX_VALUE) { System.out.println(-1); }else { System.out.println(dp[n-1][aim]); } } }