《算法导论》老师布置的作业,解决钢条切割问题:
附上代码:
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