动态规划之钢条切割

这篇博客探讨了如何使用Java实现动态规划解决钢条切割问题。文章通过具体的代码示例,详细阐述了解题思路和过程,同时提到了自定义的简单画图类辅助理解算法。
摘要由CSDN通过智能技术生成
《算法导论》老师布置的作业,解决钢条切割问题:

附上代码:

package com.crazymonkey;

import java.awt.Color;
import java.util.ArrayList;
import javax.swing.JOptionPane;

/**
 * 算法导论第15章之钢条切割
 * @author CrazyMonkey
 * @since 2013/10/16
 */
public class SteelStripCut{

	public static void main(String[] args) {

		String s = JOptionPane.showInputDialog(null, "请输入待切割钢条长度(必须为小于等于10的正整数):", "输入钢条长度",
				JOptionPane.INFORMATION_MESSAGE);
		int length = 0;
		if (s != null) {
			boolean flag = true;
			while (flag)
				try {
					length = Integer.parseInt(s);
					flag = false;

				} catch (Exception e) {
					s = JOptionPane.showInputDialog(null, "请重新输入待切割钢条长度(必须为小于等于10的正整数):",
							"输入钢条长度",
							JOptionPane.INFORMATION_MESSAGE);
				}

			Draw draw = new Draw("切割长度为 " + length + " 的结果");
			draw.setCanvasSize(length * 100, 100);
			draw.setXscale(0, length * 100);
			draw.setYscale(0, 100);
			draw.setLocation(200, 200);
			draw.filledRectangle(length * 50, 50, length * 50, 10);
			draw.setPenColor(Color.RED);
			draw.setPenRadius(0.01);

			int p = extendButtomUpCutRod(price, length);
			ArrayList<Integer> record = new ArrayList<Integer>();
			while (length > 0) {
				record.add(save[length]);
				length -= save[length];
			}

			int start = 0;
			for (int i = 0; i < record.size(); i++) {

				start += record.get(i) * 100;
				int x = start;
				int y0 = 30;
				int y1 = 70;
				if (i != record.size() - 1)
					draw.line(x, y0, x, y1);
				draw.text(x - record.get(i) * 50, 70, record.get(i) + "");
			}
			draw.textLeft(length * 100, 20, "最大利润为:" + p);
			draw.show();
		}

	}

	/**
	 * 自顶向下的递归实现
	 * 
	 * @param p
	 *            价格列表
	 * @param n
	 *            初始长度
	 * @return 最大利益
	 */
	public static int cutRod(int[] p, int n) {
		if (n == 0)
			return 0;
		earnings = p[0];
		for (int i = 1; i <= n; i++)
			earnings = Math.max(earnings, p[i] + cutRod(p, n - i));
		return earnings;

	}

	/**
	 * 带备忘的自顶向下的实现
	 * 
	 * @param p
	 *            价格列表
	 * @param n
	 *            初始长度
	 * @return 最大利益
	 */
	public static int memoizedCutRod(int[] p, int n) {
		int[] revenue = new int[n + 1];
		for (int i = 0; i < n + 1; i++)
			revenue[i] = p[0];
		return memoizedCutRodAux(p, n, revenue);
	}

	private static int memoizedCutRodAux(int[] p, int n, int[] r) {

		if (r[n] >= 0)
			return r[n];
		if (n == 0)
			earnings = 0;
		else
			earnings = p[0];
		for (int i = 1; i <= n; i++)
			earnings = Math
					.max(earnings, p[i] + memoizedCutRodAux(p, n - i, r));
		r[n] = earnings;
		return earnings;

	}

	/**
	 * 带备忘的自底向上的实现
	 * 
	 * @param p
	 *            价格列表
	 * @param n
	 *            初始长度
	 * @return 最大利益
	 */
	public static int buttomUpCutRod(int[] p, int n) {
		int[] revenue = new int[n + 1];

		revenue[0] = 0;
		for (int i = 1; i <= n; i++) {
			earnings = p[0];
			for (int j = 1; j <= i; j++)
				earnings = Math.max(earnings, p[j] + revenue[i - j]);
			revenue[i] = earnings;
		}
		return revenue[n];

	}

	/**
	 * 扩展的自底向上切割
	 * 
	 * @param p
	 * @param n
	 * @return
	 */
	public static int extendButtomUpCutRod(int[] p, int n) {
		int[] revenue = new int[n + 1];
		save = new int[n + 1];
		revenue[0] = 0;

		for (int i = 1; i <= n; i++) {
			earnings = p[0];
			for (int j = 1; j <= i; j++) {

				if (earnings < p[j] + revenue[i - j]) {
					earnings = p[j] + revenue[i - j];
					save[i] = j;
				}
				revenue[i] = earnings;
			}
		}
		return revenue[n];
	}

	/**
	 * 打印最优解
	 * 
	 * @param p
	 * @param n
	 */
	public static void print(int[] p, int n) {
		extendButtomUpCutRod(p, n);
		while (n > 0) {
			System.out.print(save[n] + " ");
			n -= save[n];
		}

	}

	/*
	 * 钢条价目表 预先给定
	 */
	private static final int[] price = { Integer.MIN_VALUE, 1, 5, 8, 9, 10, 17,
			17, 20, 24, 30 };
	private static int earnings = 0;

	private static int[] save;

}

上张图:


该代码中遇到的画图类是自己开发的简单的一个类,提供了非常基本的画图方法,附上代码:

package com.crazymonkey;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.util.LinkedList;
import java.util.TreeSet;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.util.ArrayList;

/**
 * 绘图类,此类实例提供基本的绘图支持,包括:<br>
 * <ul>
 * <li>基本几何图形</li>
 * <li>图片</li>
 * <li>文本</li>
 * </ul>
 * <br>
 * <p>
 * 此类对象提供对基本事件的支持,例如鼠标移动,键盘按键处理等事件。用例只需要实现{@link DrawListener}接口,
 * 就可以完成对基本事件的处理。另外,此类实例提供了将画布上的图像保存为实际图片的功能。
 * 
 * @author CrazyMonkey
 */

public final class Draw implements ActionListener, MouseListener,
		MouseMotionListener, KeyListener {

	

	/**
	 * 创建一个默认的绘图对象
	 */
	public Draw() {
		init();
	}

	/**
	 * 创建一个指定标题的绘图对象
	 * 
	 * @param name
	 *            绘图窗口标题
	 */
	public Draw(String name) {
		this.name = name;
		init();
	}

	/*
	 * 框架、面板、画布等初始化
	 */
	private void init() {

		if (frame != null)
			frame.setVisible(false);
		frame = new JFrame();
		offscreenImage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_ARGB);
		onscreenImage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_ARGB);
		offscreen = offscreenImage.createGraphics();
		onscreen = onscreenImage.createGraphics();
		setXscale();
		setYscale();
		offscreen.setColor(DEFAULT_CLEAR_COLOR);
		offscreen.fillRect(0, 0, width, height);
		setPenColor();
		setPenRadius();
		setFont();
		clear();

		// 抗锯齿处理
		RenderingHints hints = new RenderingHints(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		hints.put(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		offscreen.addRenderingHints(hints);

		// 填充框架
		ImageIcon icon = new ImageIcon(onscreenImage);
		JLabel draw = ne
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值