1. 程式人生 > >演算法題目——蓄水池問題

演算法題目——蓄水池問題

                     

題目:  給出了指定高度的任意兩個板子,每個木板位置間隔相等,由你隨機組合,怎麼實現裝最多的水。

分析:假設水池厚度相同,於是水容量計算公式:

                                                      水容量 =  板子距離*板子高度

                                                      板子距離:兩元素的索引之差

                                                      板子高度:兩元素的最小值

解題思路:

               看到這道題目,首先可以肯定的是用窮舉法肯定能解決,這裡就不多介紹了,大家可以參考一下這篇文章

             這裡我們採用的方法是:

               1、 從最大寬度開始(即從陣列兩端開始,左記為L,右記為R),求出最大寬度下的面積,比較兩埠位置的值;

               2、對值較小的一邊的埠索引值進行調整(左埠的話+1,右埠的話-1);

              3、比較變化後的埠位置上的值是否大於調整前的值,是的話執行第4步,否則先判斷左埠是否仍小於右埠索引值,是的話再次執行第二步,否的話執行第4步;

               4、計算此寬度下的最大面積,與最大面積比較,保留最大面積值,判斷左埠索引值是否仍小於右埠索引值,是的話再次執行第二步(縮小寬度),否的話跳出迴圈;

            上面方法第三步主要是減少不必要的求面積操作,加快比較速度。

            實現程式碼如下:

package com.liao.algorithm;

import java.util.Random;

public class WaterTank {
	public static void main(String[] args) {
		int len = 10;
		int max = 10;
		WaterTank wt = new WaterTank();
		// 生成一個隨機陣列
		int[] ns = wt.generateArray(len, max);
		wt.seekMaxArea(ns);
	}

	/*
	 * 生成一個隨機陣列 陣列長度為n,陣列中最大值為max
	 */
	public int[] generateArray(int n, int max) {
		int[] ns = new int[n];
		for (int i = 0; i < n; i++) {
			Random ran = new Random();
			ns[i] = ran.nextInt(max) + 1;
			System.out.print(ns[i] + ",");
		}
		return ns;
	}

	/*
	 * 尋找最大面積 從 陣列兩端開始
	 */
	public void seekMaxArea(int[] ns) {
		int l = ns.length;// 陣列長度
		int i = 0;// 陣列前端
		int j = l - 1;// 陣列後端
		int max = j * Math.min(ns[i], ns[j]);// 初始面積
		int s, a;//中間變數
		while (i < j) {
			if (ns[i] < ns[j]) {
				a = i;
				while (ns[a] >= ns[++i] && i < j) {
					//ns[a]不小於ns[++i]且i小於j,則i繼續加1,無需跳出迴圈求面積再做比較
					continue;
				}
			} else {
				a = j;
				while (ns[a] >= ns[--j] && i < j) {
					//ns[a]不小於ns[--j]且i小於j,則j繼續減1,無需跳出迴圈求面積再做比較
					continue;
				}
			}
			s = (j - i) * Math.min(ns[i], ns[j]);//求此時的面積
			if (s > max) {
				max = s;
			}
		}
		System.out.println("最大蓄水量為" + max);
	}
}