题目描述:
描述
进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别。一条独木舟最多只能乘坐两个人,且乘客的总重量不能超过独木舟的最大承载量。我们要尽量减少这次活动中的花销,所以要找出可以安置所有旅客的最少的独木舟条数。现在请写一个程序,读入独木舟的最大承载量、旅客数目和每位旅客的重量。根据给出的规则,计算要安置所有旅客必须的最少的独木舟条数,并输出结果。
输入
第一行输入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); //进行下一列的操作
}
}
}