0-1背包算法
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
int V = in.nextInt();
int[] weight =new int[N];
int[] value =new int[N];
for (int i=0;i<N;i++){
weight[i]= in.nextInt();
}
for (int i=0;i<N;i++){
value[i]= in.nextInt();
}
int[][] dp =new int[N+1][V+1];
for (int i=1;i<N+1;i++){
int w=weight[i-1];
int v=value[i-1];
for (int j=1;j<V+1;j++){
if (j<w){
dp[i][j]=dp[i-1][j];
}else {
dp[i][j]=Math.max(dp[i-1][j-w]+v,dp[i-1][j]);
}
}
}
System.out.println(dp[N][V]);
//逆推找出装入背包的所有商品的编号
int j=V;
String numStr="";
for(int i=N;i>0;i--){
//若果dp[i][j]>dp[i-1][j],这说明第i件物品是放入背包的
if(dp[i][j]>dp[i-1][j]){
numStr = i+" "+numStr;
j=j-weight[i-1];
}
if(j==0)
break;
}
}
}
多重背包问题
/**
* 多重背包
*
* @param args
*/
public static int manyPack(int V,int N,int[] weight,int[] value,int[] num){
//初始化动态规划数组
int[][] dp = new int[N+1][V+1];
//为了便于理解,将dp[i][0]和dp[0][j]均置为0,从1开始计算
for(int i=1;i<N+1;i++){
for(int j=1;j<V+1;j++){
//如果第i件物品的重量大于背包容量j,则不装入背包
//由于weight和value数组下标都是从0开始,故注意第i个物品的重量为weight[i-1],价值为value[i-1]
if(weight[i-1] > j)
dp[i][j] = dp[i-1][j];
else{
//考虑物品的件数限制
int maxV = Math.min(num[i-1],j/weight[i-1]);
for(int k=0;k<maxV+1;k++){
dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-k*weight[i-1]]+k*value[i-1]);
}
}
}
}
return dp[N][V];
}
完全背包问题
/**
* 第二类背包:完全背包
* 因此这里是f[i][y-weight[i]]+value[i], 而不是f[i-1][y-weight[i]]+value[i]。
*/
public static String completePack(int V,int N,int[] weight,int[] value){
//初始化动态规划数组
int[][] dp = new int[N+1][V+1];
//为了便于理解,将dp[i][0]和dp[0][j]均置为0,从1开始计算
for(int i=1;i<N+1;i++){
for(int j=1;j<V+1;j++){
//如果第i件物品的重量大于背包容量j,则不装入背包
//由于weight和value数组下标都是从0开始,故注意第i个物品的重量为weight[i-1],价值为value[i-1]
if(weight[i-1] > j)
dp[i][j] = dp[i-1][j];
else
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-weight[i-1]]+value[i-1]);
}
}
//则容量为V的背包能够装入物品的最大值为
int maxValue = dp[N][V];
int j=V;
String numStr="";
for(int i=N;i>0;i--){
//若果dp[i][j]>dp[i-1][j],这说明第i件物品是放入背包的
while(dp[i][j]>dp[i-1][j]){
numStr = i+" "+numStr;
j=j-weight[i-1];
}
if(j==0)
break;
}
return numStr;
}
面额拼凑组合数
给你六种面额1、5、10、20、50、100元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0-10000的非负整数)的不同组合的个数。
链接:https://www.nowcoder.com/questionTerminal/14cf13771cd840849a402b848b5c1c93
来源:牛客网
import java.util.Scanner;
public class StringUtil {
//拼凑面额
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int arr[] = {1,5,10,20,50,100};
while(in.hasNext()){
int n = in.nextInt();
long res[] = new long[n+1];
res[0] = 1L;
for(int i=0; i<arr.length; i++){
for(int j=1; j<=n; j++){
if(j >= arr[i]){
res[j] += res[j-arr[i]];
}
}
}
System.out.println(res[n]);
}
}
}
换钱的最少货币数 0-1背包
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
sc.nextLine();
String[] S = new String[m];
for (int i = 0; i < m; i++) {
S[i] = sc.nextLine();
}
String T = sc.nextLine();
int[] dp = new int[T.length() + 1];
for (int i = 1; i < T.length() + 1; i++) {
dp[i] = dp[i - 1];
for (int j = 0; j < m; j++) {
if (i - S[j].length() >= 0)
if (T.substring(i - S[j].length(), i).equals(S[j]))
dp[i] = Math.max(dp[i],dp[i - S[j].length()] + 1);
}
}
System.out.println(dp[T.length()]);
}