欢迎讨论~
允许作业有不同的处理时间,每个作业i与一个三元组联系(pi, di, ti)。
目标:n个作业的子集合J,J中的作业都能在相应的期限内完成,且不在J中的作业招致的罚款总额最小。
例:n=4,
(p1,d1,t1)=(5,1,1),
(p2,d2,t2)=(10,3,2),
(p3,d3,t3)=(6,2,1),
(p4,d4,t4)=(3,1,1),
main.java
包含测试数据。
LCBB.java
为算法实现主体。
Node.java
是结点类。
NodeComparator.java
用于排序。
//main.java
public class Main {
public static void main(String[] args) {
int p[]=new int[]{6,3,4,8,5};
int t[]=new int[]{2,1,2,1,1};
int d[]=new int[]{3,1,4,2,4};
LCBB worker=new LCBB();
worker.lcbb(p,d,t);
}
}
//LCBB.java
import java.util.*;
public class LCBB {
Vector<Integer> parent;
LinkedList<Node> lifeNodes;
int U;
int pointNumber;
int ans;
void lcbb(int[]p,int[]d,int[]t)
{
//求惩罚最大值
int n=p.length;
int sumP=0;
for(int x:p)
{
sumP+=x;
}
//初始化
int[] newX;
ans=0;
pointNumber=0;
parent=new Vector<Integer>();
lifeNodes=new LinkedList<Node>();
//配置初始结点
Node aNode=new Node(pointNumber++,sumP,0,-1);
aNode.setX(new int[p.length]);
parent.add(-1);
lifeNodes.add(aNode);
Node childNode;//=new Node(pointNumber,sumP,0,-1);
U=sumP;
//开始添加儿子节点
while (true)
{
for (int i = aNode.thisStep + 1, sumAbandon = 0; i < n; i++) {
//配置孩子结点
childNode = new Node(pointNumber++, aNode.getU() - p[i], aNode.getC() + sumAbandon, i);
newX=new int[aNode.getX().length];
System.arraycopy(aNode.getX(),0,newX,0,newX.length);
newX[childNode.getThisStep()]=1;
childNode.setX(newX);
System.out.println(" "+aNode.getNumber()+" 生成孩子结点:"+childNode.getNumber()+" c="+childNode.getC()+" u="+childNode.getU()+" U="+U+" x="+Arrays.toString(childNode.getX()));
//给孩子结点设置爸爸
parent.add(aNode.getNumber());
sumAbandon+=p[i];//舍弃掉的结点总花费
if (isAAnswer(d,t,childNode.getX())&&childNode.getC() < U) {
//还有机会出现最优解
lifeNodes.add(childNode);
//尝试更新上界
if (childNode.getU() < U) {
U = childNode.getU();
ans = childNode.getNumber();
}
}
else
{
System.out.println("未加入");
}
}
lifeNodes.removeFirst();//移除自己
lifeNodes.sort(new NodeComparator());//排序
if (lifeNodes.isEmpty()||lifeNodes.getFirst().getC()>=U) {
//说明此时完成遍历
System.out.println("least cost=" + U);
System.out.println("parent:"+Arrays.toString(parent.toArray()));
System.out.print("顺序逆序为:");
while (ans != -1) {
System.out.print(ans + " ");
ans = parent.get(ans);
}
return;
}
//执行到此处说明没有完成遍历,算法未结束
aNode= lifeNodes.getFirst();//获取下一个结点,集合中无点也没问题,null
}
}
boolean isAAnswer(int[]d,int[]t,int[]x)
{
class LittleNode implements Comparable<LittleNode>
{
int t;
int d;
public int getT() {
return t;
}
public int getD() {
return d;
}
public LittleNode(int t, int d) {
this.t = t;
this.d = d;
}
@Override
public int compareTo(LittleNode cell) {
if(this.d==cell.d&&this.t==cell.t)
{
return 0;
}
else if(this.d>cell.d)
{
return -1;
}
else
{
return 1;
}
}
}
//将已选中的任务加入集合,集合自动排序
TreeSet<LittleNode> nodes=new TreeSet<LittleNode>();
int n=0;
for(int i=0;i<x.length;i++)
{
if(x[i]!=0)
{
nodes.add(new LittleNode(t[i],d[i]));
}
}
//开始遍历判断
boolean flag=true;
int ddl=nodes.first().getD();
while (!nodes.isEmpty())
{
ddl=Math.min(ddl,nodes.first().getD());//ddl和当前ddl最晚的任务的ddl最小值
if(ddl-nodes.first().getT()<0)
{
//时间不够了
flag=false;
break;
}
else
{
ddl=ddl-nodes.first().getT();//求最新ddl
nodes.remove(nodes.first());//移除已做过的任务
}
}
System.out.println(flag);
return flag;
}
}
//Node.java
public class Node implements Comparable<Node>{
int number;//节点的序号
int u;//上界
int c;//下界
int thisStep;//当前考虑的最后一个结点是第几个,根节点为-1,允许出现0
int[]x;//当前结点的选择
public Node(int number, int u, int c,int thisStep) {
this.number = number;
this.u = u;
this.c = c;
this.thisStep=thisStep;
}
public int getU() {
return u;
}
public int getC() {
return c;
}
public int getNumber() {
return number;
}
public int[] getX() {
return x;
}
public int getThisStep() {
return thisStep;
}
public void setX(int[] x) {
this.x = x;
}
@Override
public int compareTo(Node node) {
if(this.getC()==node.getC())//(this.getC()==node.getC()&&this.getU()==node.getU())
{
return 0;
}
else if(this.getC()<node.getC())
{
return -1;
}
else //(this.getC()>node.getC())
{
return 1;
}
}
}
//NodeComparator.java
import java.util.Comparator;
public class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node node, Node t1) {
if(node.getC()==t1.getC())
{
return 0;
}
else if(node.getC()<t1.getC())
{
return -1;
}
else //(this.getC()>node.getC())
{
return 1;
}
}
}