钢条切割问题(Java)——Bottom-up DP演算法

本文深入探讨了Bottom-up DP算法在解决RodCutting问题中的应用,通过改进Top-down DP算法减少重复计算,实现时间复杂度O(n^2)。文章详细介绍了算法的实现过程,包括读取文件、数据处理及求解最大利润。

Rod Cutting题目:

在这里插入图片描述

  • 注意:
  1. 本题采用txt文件读入,屏幕输出;
    如果需要屏幕读入屏幕输出,可以留言或者自己改代码~
  2. Bottom-up DP演算法:因为Top-down DP演算法有很多重复的计算,因此进一步改进Top-down DP演算法得到Bottom-up DP演算法。在第一次计算中把分割结果以及最大利润的结果记录下来,下次需要用到的时候直接调用,节省时间。——所需时间T=O( n^2)
import java.beans.IntrospectionException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class BottomupDP {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		long startTime = System.currentTimeMillis();
		try {
		FileReader in = new FileReader("p1.txt");
		BufferedReader inin=new BufferedReader(in);//读入文件
		 	try {
		 		String s="";
		 		int i=1;		 		
				int[] Length=new int[100];//Rod的长度
				int[] Price=new int[100];//Rod的价值
		 		while((s=inin.readLine())!=null)
		 		{  
			 		//System.out.println(s);
			 	    //将每一行分为两个整数
			 		String []data=s.split(" ");
			 		//System.out.println("长度"+data.length);
			 		int [] datas=new int[data.length];//存入每一行String类型的数组data[0]  data[1]  
			 		//将String类型数组转成int类型
			 		for(int j=0;j<data.length;j++)
			 		{   datas[j]=Integer.parseInt(data[j]); } //将String类型转换成int类型
	//		 		for(int i=0;i<datas.length;i++)
	//		 		{    System.out.println(i+" "+datas[i]+" ");   } 	
			 		Length[i]=datas[0]; //获取Rod的长度
			 		Price[i]=datas[1];  //获取Rod的价值
			 		//System.out.println(data);
			 			i++;
		 		}
//		 		for(int k=0;k<i;k++)
//		 		{    System.out.println(k+" "+Length[k]+" ");   } //Rod的长度Length
//		 		for(int k=0;k<i;k++)
//		 		{    System.out.println(k+" "+Price[k]+" ");   } //Rod的价格Price
		 		Scanner scanner=new Scanner(System.in);
		 		System.out.print("请输入Rod的长度: ");
		 		int n=scanner.nextInt();//Rod的长度
		 		System.out.println("Maximum revenue: "+extendedBottomUpCutRod(Price,n));
		 		printCutRodSol(Price,n);
		 		
		 	} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long endTime = System.currentTimeMillis();		 	
	    System.out.println("方法:Bottom-up DP算法 ; 执行时间: "+(endTime-startTime)+" ms");	
	}
	static int[] s=new int[100];
	static int extendedBottomUpCutRod(int p[] ,int n) {
		 int[] r=new int[n+1];
		 r[0]=0;
		 s[0]=0;
//	    if(r[n] != -1)
//	        return r[n];
	    for(int i = 1; i <= n; i++) {// 双层循环建立r和s数组存入切割点以及最大利润
	        int q =Integer.MIN_VALUE;
	        for(int j = 1; j <= i; j++) {
		        	if(q<p[j] + r[i - j])//q为:每个长度的Rod最大的max值
		        	{
		        		q=p[j] + r[i - j];
		        		s[i] = j;//s记录下获得最大价值的切割点
		        	}
	            }
	        //System.out.print(s[i]+" ");
	        r[i] = q;//将最大值存入r[i]
	        }
	    return r[n];
	}
	 
	static void printCutRodSol(int p[],int n) {//输出Cuts的位置
		System.out.print("Cuts:");
		while(n > 0) {
			System.out.print(s[n]+" ");//找到n对应的切割点
			n=n-s[n];
		}
		System.out.println();
	}

}

运行成功,截图如下:
在这里插入图片描述

`EXTENDED-BOTTOM-UP-CUT-ROD` 是《算法导论》中提到的一个动态规划算法,用于解决钢条切割问题。该算法通过自底向上的方式计算最优解,并记录下每个子问题的最优解以便构造最终的解。 以下是使用C++实现 `EXTENDED-BOTTOM-UP-CUT-ROD` 的代码: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; // 定义一个函数来实现 EXTENDED-BOTTOM-UP-CUT-ROD pair<vector<int>, vector<int>> extendedBottomUpCutRod(const vector<int>& p, int n) { vector<int> r(n + 1, 0); // r[i] 表示长度为 i 的钢条的最大收益 vector<int> s(n + 1, 0); // s[i] 表示长度为 i 的钢条的最优切割第一段长度 for (int j = 1; j <= n; ++j) { int maxRevenue = -1; for (int i = 1; i <= j; ++i) { if (maxRevenue < p[i] + r[j - i]) { maxRevenue = p[i] + r[j - i]; s[j] = i; // 记录当前长度 j 的最优切割方案的第一段长度 } } r[j] = maxRevenue; } return {r, s}; } // 构造切割方案 void printCutRodSolution(const vector<int>& p, int n) { pair<vector<int>, vector<int>> result = extendedBottomUpCutRod(p, n); vector<int> r = result.first; // 最大收益数组 vector<int> s = result.second; // 最优切割方案的第一段长度数组 cout << "Maximum revenue: " << r[n] << endl; cout << "Cutting solution: "; while (n > 0) { cout << s[n] << " "; n -= s[n]; } cout << endl; } int main() { // 假设价格表 p,其中 p[i] 表示长度为 i 的钢条的价格 vector<int> p = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30}; // 长度从 0 到 10 int n = 7; // 钢条的总长度 printCutRodSolution(p, n); return 0; } ``` ### 解释 上述代码实现了 `EXTENDED-BOTTOM-UP-CUT-ROD` 算法: 1. **输入**:价格表 `p` 和钢条长度 `n`。 - `p[i]` 表示长度为 `i` 的钢条的价格。 2. **输出**:最大收益 `r[n]` 和切割方案 `s`。 - `r[i]` 表示长度为 `i` 的钢条的最大收益。 - `s[i]` 表示长度为 `i` 的钢条的最优切割方案的第一段长度。 3. **核心逻辑**: - 使用两个数组 `r` 和 `s` 来存储子问题的解。 - 对于长度为 `j` 的钢条,尝试每种可能的切割位置 `i`(即切割成长度为 `i` 和 `j-i` 的两段),并更新最大收益和对应的切割方案。 4. **构造切割方案**: - 根据数组 `s` 反向追踪切割方案,直到钢条长度为 0。 运行结果: 对于长度为 7 的钢条,程序会输出最大收益和切割方案。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laura_Wangzx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值