硬币表示

xiaoxiao2021-02-28  51

1)输入最大情况100000 ,本地IDE运行时间大概在 2093毫秒,在线编辑器要求在3秒内,但是总是提示超时 /** * 硬币表示 * 题目描述:4种硬币,币值分别为 1 5 10 25 给定n,使用这些币种来表示n,求最对的表示方法 * 思路完全套用0-1背包问题,动态规划 * 讨论使用到第i种币表示j分时,能够表示的最多方法数量,涉及到2个自变量,使用二维数组维护讨论结果maxN[i][j] * 递推公式 * maxN[0][j] = 0 * maxN[i][0] = 1 * maxN[1][j] = 1 * maxN[i][j] = * { * 1) maxN[i-1][j] (j < coins[i]) * 2) maxN[i-1][j] + Sum{ maxN[i-1][j-k*coins[i]]| 1<=k<=j/coins[i] } (j >= coins[i]) 使用coins[i] 和不使用coins[i]所有情况的总和 * } */ package dp; import java.util.Scanner; public class Main { static int[] coins = {0, 1, 5, 10, 25}; static int[][] maxN = null; public static void main(String[] args){ Scanner in = new Scanner(System.in); int n = in.nextInt(); System.out.println(countWays(n)); for(int i = 1; i <= 4; i++){ for( int j = 1; j <= n; j++){ System.out.print(maxN[i][j]+" "); } System.out.println(""); } } public static int countWays(int n) { if(n < 1) return 0; maxN = new int[coins.length][n+1]; for(int j = 1; j<= n; j++){ maxN[1][j] = 1; } for(int i = 1; i <= 4; i++){ maxN[i][0] = 1; } for(int i = 2; i <= 4; i++){ for(int j = 1; j <= n; j++){ if(j < coins[i]) maxN[i][j] = maxN[i-1][j]; else{ int temp = 0; for(int k = j/coins[i]; k >= 1; k--){ temp += maxN[i-1][j-k*coins[i]]; } maxN[i][j] = maxN[i-1][j] + temp; } } } return maxN[4][n]; } } 2)优化了一下,将循环改掉就可以了,循环存在这大量的重复计算 /** * 硬币表示 * 题目描述:4种硬币,币值分别为 1 5 10 25 给定n,使用这些币种来表示n,求最对的表示方法 * 思路完全套用0-1背包问题,动态规划 * 讨论使用到第i种币表示j分时,能够表示的最多方法数量,涉及到2个自变量,使用二维数组维护讨论结果maxN[i][j] * 递推公式 * maxN[0][j] = 0 * maxN[i][0] = 1 * maxN[1][j] = 1 * maxN[i][j] = * { * 1) maxN[i-1][j] (j < coins[i]) * 2) maxN[i-1][j] + Sum{ maxN[i-1][j-k*coins[i]]| 1<=k<=j/coins[i] } (j >= coins[i]) 使用coins[i] 和不使用coins[i]所有情况的总和 * } */ package dp; import java.util.Date; import java.util.Scanner; public class Main { static int[] coins = {0, 1, 5, 10, 25}; static int[][] maxN = null; public static void main(String[] args){ Scanner in = new Scanner(System.in); int n = in.nextInt(); long t1 = new Date().getTime(); System.out.println(countWays(n)); System.out.println(new Date().getTime() - t1); } public static int countWays(int n) { if(n < 1) return 0; maxN = new int[coins.length][n+1]; for(int j = 1; j<= n; j++){ maxN[1][j] = 1; } for(int i = 1; i <= 4; i++){ maxN[i][0] = 1; } for(int i = 2; i <= 4; i++){ for(int j = 1; j <= n; j++){ if(j < coins[i]) maxN[i][j] = maxN[i-1][j]; else{ // int temp = 0; // for(int k = j/coins[i]; k >= 1; k--){ // temp += maxN[i-1][j-k*coins[i]]; // } // maxN[i][j] = maxN[i-1][j] + temp; maxN[i][j] = maxN[i-1][j] + maxN[i][j-coins[i]];//可以使用该币种但是不用的表示方法数为当前分值下前一种状态 //币种能表示的种数 maxN[i-1][j], //但是如果使用该币种,表示至少使用一个该币,那么问题可以转化为最后coins[i]的分数 //由1个coins[i]表示,即已经使用1个coins[i]的前提下,j-coins[i]分数可以由前i种币表示多少种分法?即maxN[i][j-coins[i]] } } } return maxN[4][n]; } }

转载请注明原文地址: https://www.6miu.com/read-76012.html

最新回复(0)