给定一根长度为N米的原木;另有一个分段价格表,给出长度L1,L2,...Li,...Lk米所对应的价格P1,P2...Pk(Li,Pi均为正整数),求切割原木分段出售所能获得的最大收益。 例如,根据下面给出的价格表,
Li | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
Pi | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 23 | 28 |
若要出售一段8米长的原木,最优解是将其切割为2米和6米的两段,这样可以获得最大收益=L2+L6=5+17=22。而若要出售一段3米长的原木,最优解是根本不要切割,直接售出。
输入格式:
首行输入N,k,紧接着第二行为k个Li(递增有序)和第三行对应的k个Pi值。 (0<N,k<1000) 。
输出格式:
对应原木的最大切割收益(题目中保证最大收益值在int范围)。
输入样例:
在这里给出一组输入。例如:
8 10
1 2 3 4 5 6 7 8 9 10
1 5 8 9 10 17 17 20 23 28
结尾无空行
输出样例:
在这里给出相应的输出。例如:
22
结尾无空行
解题思路:
类似于01背包问题 ,解决这道题首先得理解动态规划中的经典案例(01背包)
听懂不翻车系列之--背包问题(01背包 完全背包 多重背包 二维费用背包)_哔哩哔哩_bilibili
建议初学者好好看一下理解一下背包问题!!!
最重要的是:状态转移方程----dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);(二维数组)
----dp[j]=max(dp[j],dp[j-w[i]]+v[i]);(滚动数组)
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
0 | 1 | 5 | 6 | 6 | 6 | 6 | 6 | 6 |
0 | 1 | 5 | 8 | 9 | 13 | 14 | 14 | 14 |
0 | 1 | 5 | 8 | 9 | 13 | 14 | 17 | 18 |
0 | 1 | 5 | 8 | 9 | 13 | 14 | 17 | 18 |
0 | 1 | 5 | 8 | 9 | 13 | 17 | 18 | 22 |
0 | 1 | 5 | 8 | 9 | 13 | 17 | 18 | 22 |
0 | 1 | 5 | 8 | 9 | 13 | 17 | 18 | 22 |
0 | 1 | 5 | 8 | 9 | 13 | 17 | 18 | 22 |
0 | 1 | 5 | 8 | 9 | 13 | 17 | 18 | 22 |
1.二维dp数组
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner n=new Scanner(System.in);
int a=n.nextInt(); //背包重量
int b=n.nextInt(); //物品个数
n.nextLine();
int [] w=new int[35]; //物品重量
int [] v=new int[35]; //物品价值
for(int i=1;i<=b;i++) {
w[i]=n.nextInt();
}
n.nextLine();
for(int i=1;i<=b;i++) {
v[i]=n.nextInt();
}
int [][]dp=new int[35][205]; //dp动态数组
for(int i=1;i<=b;i++) {
for(int j=1;j<=a;j++) {
if(j<w[i]) {
dp[i][j]=dp[i-1][j];
}
else {
dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
}
}
}
System.out.println(dp[b][a]);
}
}
2.滚动dp数组(简化二维数组)
import java.util.Scanner;
public class Main2 {
public static void main(String[] args) {
Scanner n=new Scanner(System.in);
int a=n.nextInt(); //背包重量
int b=n.nextInt(); //物品个数
n.nextLine();
int [] w=new int[1005]; //物品重量
int [] v=new int[1005]; //物品价值
for(int i=1;i<=b;i++) {
w[i]=n.nextInt();
}
n.nextLine();
for(int i=1;i<=b;i++) {
v[i]=n.nextInt();
}
int []dp=new int[1005]; //dp动态数组
for(int i=1;i<=b;i++)
{
for(int j=w[i];j<=a;j++)
{
dp[j]=Math.max(dp[j], dp[j-w[i]]+v[i]);
}
}
System.out.println(dp[a]);
}
}
总结:提交pta平台时,二维dp数组通过不了,个人感觉原因是太浪费内存(大佬有意见可以指点小弟),只有滚动数组可以通过。