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