首先就我自己对带有期限的作业排序问题做一番描述:有n个待完成的作业,其中任何一个作业都能在单位时间内完成,并且都有各自完成的期限。每个作业只有在给定的期限之前完成才能得到相应的效益值。
程序之前的例子: 待完成的作业 Jobs[] = {1,2,3,4}
作业完成的期限 deadLines={2,1,2,1}
完成作业所带来的收益 profits={10,20,9,8}
可行解如下:
完成的作业 | 完成顺序 | 得到的收益 |
---|---|---|
1 | 1 | 10 |
2 | 2 | 20 |
3 | 3 | 9 |
4 | 4 | 8 |
{1,2} | {2,1} | 30 |
{1,3} | {1,3}或者{3,1} | 19 |
{1,4} | {4,1} | 18 |
{2,3} | {2,3} | 29 |
{3,4} | {4,3} | 17 |
一般都会在面临众多选择的情况下,选择最好的。那就是在众多的可行解中选择收益最高的作业集合进行完成。
比较苯的原因,我用了一天的时间,才把书上写的带有期限的作业排序算法看懂。所以我宁愿相信那些个收益是惩罚值,因为比较苯的人,是很可能在规定的期限前完不成作业,而受到相应的惩罚,呵呵。
首先我把作业本身抽象出一个Job类代码如下:
package com.yemao.job;
public class Job {
//作业序号
private int jobId;
//作业期限
private int jobDeadLine;
//未在给定期限前完成作业的惩罚
private int jobPunishValue;
//不带参数的构造函数
public Job(){}
//带参数的构造函数
public Job(int jobId,int jobDeadLine,int jobPunishValue){
this.jobId = jobId;
this.jobDeadLine = jobDeadLine;
this.jobPunishValue = jobPunishValue;
}
public int getJobId() {
return jobId;
}
public int getJobDeadLine() {
return jobDeadLine;
}
public int getJobPunishValue() {
return jobPunishValue;
}
}
然后就是在众多的可行解中寻求一个最佳解的问题,按照贪心算法,先选择一个量度标准。我这里选择的量度标准是:当前考虑的作业是受到的惩罚值最小的作业。所以我先要将现有的待排序的作业按照非降序的顺序排序。然后将满足条件的作业计入解集合。
代码如下:
package com.yemao.job;
public class FJB {
//作业排序的结果集
int[] j = null;
//待安排的作业
private Job[] jobs = {
new Job(1,1,0)
,new Job(2,5,70)
,new Job(3,3,60)
,new Job(4,4,50)
,new Job(5,4,40)
,new Job(6,2,30)
,new Job(7,5,20)
,new Job(8,6,10)
};
//驱动程序
public static void main(String [] args){
FJB fjb = new FJB();
fjb.sortJob();
}
/**
* 作业排序的实现
*/
private void sortJob(){
//将待安排的作业进行排序
sortJobs();
//初始化作业的解空间
j = new int[jobs.length];
//查看解空间的初始状态
System.out.println("初始状态解空间为:");
for(int m:j){
System.out.print(m+" ");
}
System.out.println();
//首先计入第一个作业
j[0] = jobs[0].getJobId();
//记录当前解空间作业的最后一个作业
int k = 1;
for(int i = 1; i < jobs.length; i++){
//拿到解空间的最后一个作业的位置
int r = k;
//如果当前最后作业的完成期限比当前要完成的作业的作业期限还大的时候
//并且当前最后的作业的完成期限还能容纳在它的前面插入新的作业
while(jobs[r-1].getJobDeadLine() > jobs[i].getJobDeadLine() && jobs[r-1].getJobDeadLine() != r)
{
//当前作业的位置向前移一个位置
r = r - 1;
}
//如果当前最后作业的完成期限还是小于等于当前考虑作业的完成期限
//并且当前完成作业的期限大于当前的最大位置
if(jobs[r-1].getJobDeadLine() <= jobs[i].getJobDeadLine() && jobs[i].getJobDeadLine() > r){
for(int n=k-1;n >= r; n--){
j[n+1] = j[n];
}
//尤其是在数组是从零开始的时候,这个地方的下标应该是r而不是r+1
j[r] = jobs[i].getJobId();
k = k + 1;
}
//查看每一次插入的位置及考虑的惩罚值是否正确
System.out.println("当前插入作业的信息为 : 序号为("
+ jobs[i].getJobId()
+") 期限为( "
+jobs[i].getJobDeadLine()
+") 惩罚值为("
+jobs[i].getJobPunishValue()
+")"
);
for(int h = 0;h < k ; h++){
if(h != r){
System.out.print(j[h]+" ");
}else{
System.out.print(" ("+j[h]+") ");
}
}
System.out.println();
}
//输出结果
/*System.out.println("排序的结果为: ");
for(int i=0;i
System.out.print(""+j[i]+" ");
}*/
}
/**
* 将作业按照惩罚值的升序进行排序
* 应用方法为冒泡排序
*/
private void sortJobs(){
for(int i = 0;i < (jobs.length -1); i++){
for(int j = i+1;j < jobs.length; j++){
if(jobs[i].getJobPunishValue() > jobs[j].getJobPunishValue()){
Job tempJob = jobs[i];
jobs[i] = jobs[j];
jobs[j] = tempJob;
}
}
}
//打印排序的结果看是否正确
/* for(int k = 0;k < jobs.length; k++){
System.out.println(jobs[k].getJobPunishValue());
}*/
}
}
以上是我注册csdn后的第一篇文章,动机很单纯。就是想得到积分。因为我想下载一个资源,碍于积分不够。呵呵,不过,话又说回来,我更希望我写的东西对某些人有所帮助。我很笨,可是一直在努力,渴望能成为一个有所用的人。希望能和各位朋友一起成长。