貪心算法_乘船問題

題目描述:

描述 
進行一次獨木舟的旅行活動,獨木舟可以在港口租到,並且之間沒有區別。一條獨木舟最多隻能乘坐兩個人,且乘客的總重量不能超過獨木舟的最大承載量。我們要儘量減少這次活動中的花銷,所以要找出可以安置所有旅客的最少的獨木舟條數。現在請寫一個程序,讀入獨木舟的最大承載量、旅客數目和每位旅客的重量。根據給出的規則,計算要安置所有旅客必須的最少的獨木舟條數,並輸出結果。
輸入 
第一行輸入s,表示測試數據的組數; 
每組數據的第一行包括兩個整數w,n,80<=w<=200,1<=n<=300,w爲一條獨木舟的最大承載量,n爲人數; 
接下來的一組數據爲每個人的重量(不能大於船的承載量); 
輸出 
每組人數所需要的最少獨木舟的條數。
樣例輸入 

85 6 
5 84 85 80 84 83 
90 3 
90 45 60 
100 5 
50 50 90 40 60
樣例輸出 


3

今天剛參加完學校的程序設計大賽。很遺憾沒有把這個題目給做完,期間機器出了點問題,而且運行的myeclipse8.5有點卡。

但是回來之後我慮了一下思路:下面說一下我自己的思路,我自己用的遞歸方法,邊調試邊修改出來的。

1、設置相關的變量。


	static int[] MaxWeight = null; //最大的載重量
	static int s = 0;
        static int n = 0;// 人數
	static int[] BoardNum = null; // 船的數量
	static int[][] PW = null;   //所有人的重量
	static int[] PW1 = null;	//一次測試人的重量
	static int Weights = 0;//把重量都加起來

2、對數據進行排序,先從輕的人開始計算,如果不滿足條件(目前的重量和 大於 或者 等於  船的最大載重量)就繼續算Weights重量的和。如果目前的總重量Weights和 等於了 船的最大載重量MaxWeight,就將BoardNum++;如果目前的總重量Weights大於了MaxWeight,也將BoardNum++,同時(關鍵的問題了)將列數據 j--(假設你的MaxWeight爲 90,且所有人的重量已經在PW二維數組中排好序了,現在有3個人的體重爲:45 60 90,45+60=105,滿足要求,BoradNum++ ,然後進行下一次的判斷,判斷 60和 90的人 的重量,如果你不把列數據--的話,就不能再用到60斤的這個人了,相當於把它給扔了,這裏仔細體會一下)。然後進行下一次遞歸將j+1;就羅嗦這麼多了,具體的看正確的代碼。

在我的代碼裏面覺得重要的是,2個變量的聲明,一個是PW,所有人的重量都保存在這裏,然後一個是PW1,保存測試一次的數據,然後用copyOf到PW數組裏面去。爲什麼要這樣做?看我下面的註釋(我考試的時候問題就出在了這裏,測試一次的結果是正確的,但是測試輸入3次,結果就是錯誤的,前面2次是0,最後一次是3),下面看我考試的時候的(錯誤)算法。

public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		s = input.nextInt(); //測試數據的組數
		MaxWeight = new int[s]; //開闢相應的數組,保存每隻船的最大重量
		BoardNum = new int[s]; //船的數量
		for (int i = 0; i < s; i++) {
			MaxWeight[i] = input.nextInt();
			n = input.nextInt(); //人數
			PW = new int[s][n];  //開闢s組,n個人的數組。    //問題就出現在這裏的。不知道大家看到了沒有,如果s爲1,也就
//測試一組數據的時候,這裏的new[s][n]只運行了一次,沒問題,但是當你s爲3的時候,會new3個,每次會把數據給清0,所以我在下面想了一個辦法
			for(int j = 0;j < n; j++) {
				PW[i][j] = input.nextInt();
			}
		Arrays.sort(PW[i]);
		Fun(PW, 0, 0);
		for (int i = 0; i < s; i++)
			System.out.println(BoardNum[i]);
}


下面請看正確的代碼:

import java.util.Scanner;
import java.util.Arrays;

public class 運輸船的數量 {
	static int s = 0;
	static int[] MaxWeight = null; // 最大的載重量
	static int n = 0;// 人數
	static int[] BoardNum = null; // 船的數量
	static int[][] PW = null; // 所有人的重量
	static int[] PW1 = null; // 一次測試人的重量
	static int Weights = 0;

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		s = input.nextInt();
		MaxWeight = new int[s];
		BoardNum = new int[s];
		PW = new int[s][];   //初始化所有的人的重量數組
		for (int i = 0; i < s; i++) {
			MaxWeight[i] = input.nextInt();
			n = input.nextInt();
			PW1 = new int[n];   
			for (int j = 0; j < n; j++) {
				PW1[j] = input.nextInt();
			}
			PW[i] = Arrays.copyOf(PW1, PW1.length); //將數據copy到PW中,這樣就避免了被清零
			Arrays.sort(PW[i]);
		}
		Fun(PW, 0, 0);  //調用遞歸
		for (int i = 0; i < s; i++)
			System.out.println(BoardNum[i]);
	}

	public static void Fun(int[][] Pw, int i, int j) {
		if (j == Pw[i].length) { //如果一列已經遍歷完了,就對列置零,行進行+1操作
			j = 0;
			if (i < s ) {   //不超過s-1 包括s-1
				if ((i + 1) < s) //因爲下面要進行i+1,進行下一行的遍歷,這裏避免出界
					Fun(Pw, i + 1, j);
			} else {
				return;
			}
		} else {
			Weights += Pw[i][j];       //累加重量,等於最大重量和大於最大重量處理情況不同
			if (Weights == MaxWeight[i]) { //等於的話,就直接進行下一列的操作
				BoardNum[i]++;
				Weights = 0;
			} else if (Weights > MaxWeight[i]) { //大於的話,在進行下一列操作之前還有對列///進行回滾,j--,要用到上一個數
				BoardNum[i]++;
				Weights = 0;
				j--;
			}
			Fun(Pw, i, j + 1);  //進行下一列的操作
		}
	}
}
發佈了33 篇原創文章 · 獲贊 195 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章