使用贪心法求解会议安排问题。有一组会议A和一组会议室B,A[i]表示第i个会议参加的人数,B[i]表示第i个会议室可以容纳的人数。给定数组A和数组B,试问最多可以同时举办多少个会议。例如,A[]={1,2,3},B[]={3,2,4},结果为3;若A []={3,4,3,1},B[]={1,2,2,6},结果为2。
1、首先关于贪心法的思想:只根据当前已有信息做出选择,在某种意义上并不是从整体最优考虑问题,每一次做出的选择都是从局部最优的角度思考问题,所以贪心法求解的结果不一定是整体最优解,当然在有些情况下可能会是最优解,但是基本贪心法求解的结果为为整体最优解的近似解,因为从局部最优的角度考虑问题也即是局部最优解。
2、编程实现该问题的基本思路
问题是要求出最多同时可以举办多少个会议,利用贪心法的思想。会议室容量最大的应该尽量提供给开会人数最多的会议组,同理会议室容量次大的应该提供给开会人数次多的,依次类推。
在这里会议数和会议室的数量不应该是固定的,所以两个数组的长度是个变量需要手动输入其个数。从题目中举的例子:其会议室与其会议的数组长度相同,所以数组长度的变量可以使用同一变量n来表示,当然实际情况中其数量不一定相同,这里无非多输入一个数组长度变量,对于整体没有太大的影响在代码中稍加改动就行,整体的结构不变。
代码核心片段:
public static int Amount(int[] A,int[] B,int n,int m) {
int count=0;
int j=m-1;
suanfa.Kuaipai.QuickSort(A, 0, n-1);//对每个会议的人数进行快速排序
suanfa.Kuaipai.QuickSort(B, 0, m-1);//对每个会议室能容纳的人数进行快速排序
for(int i=n-1;i>=0;) {//i从n-1开始向前推进j也是从n-1开始向前推进
if(A[i]<=B[j]) {//当会议的人数小于等于会议室容量的时候count++,同时i++,j++
count++;
i--;
j--;
}
else {
i--;
}
}
return count;
}
注释:里面suanfa.Kuaipai.QuickSort()排序算法没有给出,这里我采用的是快速排序,你也可采用其他进行排序,快速排序在我另一个文章里面有写,感兴趣可以看看。
1、当会议数和会议室数采用相同的数组变量的时候:
Java代码如下:(以下适合完成实验要求,不过题目本身就是有问题给出的例子和实际有偏差,即会议人数不可能小于等于1,会议室的数量基本是不会小于1的)比较结合现实情况的请看下一段代码
package practical;
import java.util.Scanner;
public class MeetArrange {
public static int Amount(int[] A,int[] B,int n) {
int count=0;
int j=n-1;
suanfa.Kuaipai.QuickSort(A, 0, n-1);//对每个会议的人数进行快速排序
suanfa.Kuaipai.QuickSort(B, 0, n-1);//对每个会议室能容纳的人数进行快速排序
for(int i=n-1;i>=0;) {//i从n-1开始向前推进j也是从n-1开始向前推进
if(A[i]<=B[j]) {//当会议的人数小于等于会议室容量的时候count++,同时i++,j++
count++;
i--;
j--;
}
else {
i--;
}
}
return count;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("输入要举办会议的个数为:");
int n=sc.nextInt();
int[] A=new int[n];
int[] B=new int[n];
System.out.println("输入每个会议的人数各是多少:");
for(int i=0;i<n;i++) {
A[i]=sc.nextInt();
}
System.out.println("输入各个会议室所能容纳的会议人数:");
for(int j=0;j<n;j++) {
B[j]=sc.nextInt();
}
sc.close();
System.out.println("可同时举办的会议个数为:"+Amount(A,B,n));
}
}
2、Java代码如下所示:(该代码比上一个代码完整些更结合现实情况,当时还是不够完美,仍然得继续改进,主要还是对于输入数据的约束条件进行改进)
```java
package practical;
import java.util.Scanner;
public class MeetArrange1 {
public static int Amount(int[] A,int[] B,int n,int m) {
int count=0;
int j=m-1;
suanfa.Kuaipai.QuickSort(A, 0, n-1);//对每个会议的人数进行快速排序
suanfa.Kuaipai.QuickSort(B, 0, m-1);//对每个会议室能容纳的人数进行快速排序
for(int i=n-1;i>=0;) {//i从n-1开始向前推进j也是从n-1开始向前推进
if(A[i]<=B[j]) {//当会议的人数小于等于会议室容量的时候count++,同时i++,j++
count++;
i--;
j--;
}
else {
i--;
}
}
return count;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("输入要举办会议的个数为:");
int n=sc.nextInt();
if(n<0) {//输入会议的个数不可能为负数
System.out.println("输入数据不合法,会议的数量不能小于0,请重新输入。");
n=sc.nextInt();
}
System.out.println("输入会议室的个数为:");
int m=sc.nextInt();
if(m<1) {//实际情况中一个公司或者什么单位会议室基本不可能一个没有所以对此作出限制
System.out.println("输入数据不合法,会议室的数量不能小于1,请重新输入。");
m=sc.nextInt();
}
int[] A=new int[n];
int[] B=new int[m];
System.out.println("输入每个会议的人数各是多少:");
for(int i=0;i<n;) {
A[i]=sc.nextInt();
if(A[i]<=1) {
System.out.println("输入的开会人数不合法,请重新输入");
}
else {
i++;
}
}
System.out.println("输入各个会议室所能容纳的会议人数:");
for(int j=0;j<m;) {
B[j]=sc.nextInt();
if(B[j]<=1) {
System.out.printf("输入的会议室容量不合法,请重新输入");
}
else {
j++;
}
}
sc.close();
System.out.println("可同时举办的会议个数为:"+Amount(A,B,n,m));
}
}
运行结果截图:
以上为贪心法求解最多同时安排多少个会议问题,以上代码的核心片段是不变的,要想更接近实际要改进的地方是对输入数据条件进行约束改进。
写的比较匆忙,后续可能还会修改,有什么不对或者不懂的地方大家彼此交流学习。