算法-03 贪心和分治

1 贪心算法 加勒比海盗偷财宝

场景:海盗来到了召唤师峡谷,然后丝血准备逃生。但是仍然贪图财宝。现在时间有限,必须要把容量一定的背包里装下最多的财富。
思路:按照性价比把所有宝藏排序。然后按照性价比的顺序往包里装。

	// 包的最大容量
	private int MAX_WEIGHT = 120;
	// 每个宝藏的重量
	private int[] weights = new int[] { 35, 30, 60, 50, 40, 10, 25 };
	// 每个宝藏的价值
	private int[] values = new int[] { 10, 40, 30, 50, 35, 40, 30 };
public static void main(String[] args) {
		GreedyPractice greedyPractice = new GreedyPractice();
		greedyPractice.getMaxValue(greedyPractice.MAX_WEIGHT,
				greedyPractice.weights, greedyPractice.values);
	}
	/**
	 * 获取宝藏的最大价值
	 */
	public void getMaxValue(int capacity, int[] weight, int[] values) {
		int size = weight.length;

		// 性价比的下标 按照性价比进行排序后 这个下标将会记录 之前的下标
		int[] indexArray = new int[size];

		// 性价比
		double[] costPerformance = new double[size];
		for (int i = 0; i < size; i++) {
			costPerformance[i] = (double) values[i] / weights[i];
			indexArray[i] = i;
		}

		// 按照性价比进行排序
		for (int i = 0; i < size; i++) {
			for (int j = 0; j + 1 < size - i; j++) {
				if (costPerformance[j] < costPerformance[j + 1]) {
					double temp = costPerformance[j];
					costPerformance[j] = costPerformance[j + 1];
					costPerformance[j + 1] = temp;
					int tempIndex = indexArray[j];
					indexArray[j] = indexArray[j+1];
					indexArray[j + 1] = tempIndex;
				}
			}
		}

		// 按照性价比排序的宝藏的质量和价值
		int[] w = new int[size];
		int[] v = new int[size];

		for (int i = 0; i < size; i++) {
			w[i] = weight[indexArray[i]];
			v[i] = values[indexArray[i]];
		}
		
		//包里装的宝藏
		List<Integer> pacageContent = new ArrayList<Integer>();
		// 开始遍历所有的宝藏 如果宝藏的质量比包的容量小 就装进去
		for (int i = 0; i < size; i++) {
			if (w[i] < capacity) {
				capacity = capacity - w[i];
				pacageContent.add(w[i]);
			}
		}

		for (int a : pacageContent) {
			System.out.println(a + "");
		}
	}

2 分治算法 NBA循环赛日程安排

现在假设有8支队伍打比赛,那么假设第一天1和2打,3和4打,5和6打,7和8打。那么就有如下图的安排表。一共要打七天会打完。现在要把这个图分开四个部分来表示。

这里写图片描述

public static void main(String[] args) {
		DisPatchPractice dispatch = new DisPatchPractice();
		int table[][] = new int[8][8];

		dispatch.getNBAGamePlan(table, 8);

		for (int i = 0; i < table.length; i++) {
			System.out.println();
			for(int j=0;j<table.length;j++){
				System.out.print(" "+table[i][j]);
			}
		}

	}

3 分治算法 特殊点用L形数字包围

我实在不知道这个算法该怎么去描述,总之就是把一个特殊点用L给包围起来
这里写图片描述

private void getNBAGamePlan(int[][] table, int n) {
		if (n == 1) {
			table[0][0] = 1;
		} else {
			int m = n / 2;
			// 填充左上部分
			getNBAGamePlan(table, m);

			// 填充右上部分
			for (int i = 0; i < m; i++) { // 0,1,2,3
				for (int j = m; j < n; j++) { // 4,5,6,7
					table[i][j] = table[i][j - m] + m;
				}
			}

			// 填充左下部分
			for (int i = m; i < n; i++) {// 4,5,6,7
				for (int j = 0; j < m; j++) { // 0,1,2,3
					table[i][j] = table[i-m][j] + m;
				}
			}

			// 填充右下部分
			for (int i = m; i < n; i++) { // 4,5,6,7
				for (int j = m; j < n; j++) { // 4,5,6,7
					table[i][j] = table[i - m][j - m];
				}
			}
		}

	}
	// 棋盘
	private int[][] board;
	// 特殊点的值
	int specialDot = 0;

	public ChessBoard(int specialRow, int specialCol, int size) {
		super();
		this.board = new int[size][size];
		createChessBoard(specialRow, specialCol, 0, 0, size);

		print();
	}

	//打印结果
	private void print() {
		for (int i = 0; i < board.length; i++) {
			System.out.println();
			for (int j = 0; j < board.length; j++) {
				System.out.print(board[i][j]+" ");
			}
		}
	}

	public static void main(String[] args) {
		int speciaRow = 5;
		int specialCol = 5;
		int size = 8;
		ChessBoard chessBoard = new ChessBoard(speciaRow, specialCol, size);
	}
	/**
	 * 
	 * @param specialRow
	 *            特殊点的横坐标
	 * @param specialCol
	 *            特殊点的纵坐标
	 * @param startRow
	 *            棋盘起点的横坐标
	 * @param startCol
	 *            棋盘起点的纵坐标
	 * @param size
	 */
	private void createChessBoard(int specialRow, int specialCol, int startRow,int startCol, int size) {
		if (size == 1) {
			return;
		}
		int half = size / 2;

		specialDot = specialDot % 4 + 1;

		// 如果特殊点在左上方
		if (specialRow < startRow+half && specialCol < startCol+half) {
			createChessBoard(specialRow, specialCol, startRow, startCol, half);
		} else {
			// 如果不在左上方 那么左上方的右下角的是特殊点
			board[startRow + half - 1][startCol + half - 1] = specialDot;
			createChessBoard(startRow + half-1, startCol + half-1, startRow,startCol, half);
		}

		// 如果特殊点在右上方
		if (specialRow < startRow+half && specialCol >= startCol+half) {
			createChessBoard(specialRow, specialCol,startRow,half + startCol, half);
		} else {
			// 如果不在右上方,那么右上方的左下角是特殊点
			board[startRow + half - 1][startCol + half] = specialDot;
			createChessBoard(startRow+half-1, startCol+half, startRow, startCol + half, half);
		}

		// 如果特殊点在左下方
		if (specialRow >= startRow+half && specialCol < startCol+half) {
			createChessBoard(specialRow , specialCol, startRow+half ,startCol, half);
		} else {
			// 如果不在左下方,那么左下方的右上角是特殊点
			board[startRow + half][startCol + half - 1] = specialDot;
			createChessBoard(startRow + half, startCol + half - 1, startRow+ half, startCol, half);
		}

		// 如果特殊点在右下方
		if (specialRow >= startRow+half && specialCol >= startCol+half) {
			createChessBoard(specialRow, specialCol, startRow+ half, startCol + half, half);
		} else {
			board[startRow + half][startCol + half] = specialDot;
			createChessBoard(startRow + half, startCol + half, startRow + half,startCol + half, half);
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值