切原木问题(01背包问题)

给定一根长度为N米的原木;另有一个分段价格表,给出长度L1,L2,...Li,...Lk米所对应的价格P1,P2...Pk(Li,Pi均为正整数),求切割原木分段出售所能获得的最大收益。 例如,根据下面给出的价格表,

 

Li12345678910
Pi1589101717202328

若要出售一段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]);(滚动数组) 

dp二维数组(动态规划)
000000000
011111111
015666666
0158913141414
0158913141718
0158913141718
0158913171822
0158913171822
0158913171822
0158913171822
0158913171822

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数组通过不了,个人感觉原因是太浪费内存(大佬有意见可以指点小弟),只有滚动数组可以通过。 

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值