算法基础之贪心算法

Posted by Naah on Saturday, Sep 09,2017 11:33:44

贪心算法

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

 

算法应用

海盗装宝问题

海盗找到宝藏后,发现背包不够大,怎样装宝贝,才能最值钱呢。

/**
 * 海盗装宝
 *
 * @author Naah
 *
 */
public class haidaofenbao {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// 宝贝的重量数组
		int[] weights = new int[] { 35, 40, 60, 50, 40, 20, 25 };

		// 宝贝的价值数组
		int[] values = new int[] { 10, 200, 30, 50, 35, 80, 30 };
		haidaofenbao greedy = new haidaofenbao();

		// 背包最大重量为100
		greedy.put(100, weights, values);
	}

	/**
	 * 装宝算法
	 *
	 * @param maxWeight
	 *            背包最大重量
	 * @param weights
	 *            所有宝贝的重量数组
	 * @param values
	 *            所有宝贝的价值数组
	 */
	private void put(int maxWeight, int[] weights, int[] values) {

		// 创建所有宝贝的性价比数组
		double[] wv = new double[weights.length];

		// 创建所有宝贝的性价比下标数组
		int[] index = new int[weights.length];

		// 循环计算所有宝贝的性价比
		for (int i = 0; i < wv.length; i++) {
			wv[i] = values[i] / weights[i];
			index[i] = i;
		}

		// 以降序排序所有宝贝的性价比,以及下标
		// 优先降序排序性价比,其次优先降序排序重量
		// 简单选择排序
		for (int i = 0; i < wv.length; i++) {
			for (int j = i; j < wv.length; j++) {

				// 如果i下标性价比小于j下标性价比
				if (wv[i] < wv[j]) {

					// 交换性价比
					double temp = wv[i];
					wv[i] = wv[j];
					wv[j] = temp;

					// 交换下标
					int ind = index[i];
					index[i] = index[j];
					index[j] = ind;

					// 如果i下标性价比等于j下标性价比
				} else if (wv[i] == wv[j]) {

					// 如果i下标宝贝的重量小于j下标宝贝的重量
					if (weights[index[i]] < weights[index[j]]) {

						// 交换性价比
						double temp = wv[i];
						wv[i] = wv[j];
						wv[j] = temp;

						// 交换下标
						int ind = index[i];
						index[i] = index[j];
						index[j] = ind;
					}
				}
			}
		}

		// 创建标记装宝数组
		boolean[] flag = new boolean[weights.length];

		// 创建目前背包重量变量
		int bagWeight = 0;

		// 创建目前背包价值变量
		int bagValue = 0;

		// 循环性价比数组进行装宝
		for (int i = 0; i < wv.length; i++) {

			// 如果目前背包能把该宝贝装下
			if (weights[index[i]] + bagWeight <= maxWeight) {

				// 目前背包重量增加
				bagWeight = bagWeight + weights[index[i]];

				// 目前背包价值增加
				bagValue = bagValue + values[index[i]];

				// 标记该宝贝已装
				flag[index[i]] = true;
			}

		}

		// 输出装宝后背包的重量
		System.out.println("weight:" + bagWeight);

		// 输出装宝后背包的价值
		System.out.println("value:" + bagValue);

		// 循环输出标记数组,查看背包中装入哪些宝贝
		for (int i = 0; i < flag.length; i++) {
			System.out.print(flag[i] + " ");

		}

	}

}