求解流水作业调度和活动安排问题

1.求N个作业的最优加工顺序,采用非优先调度。 POJ 2751

采用回溯法求解(效率较低)
对应的解空间是一个排列树,也就是求1-N的全排列使完成时间最少。
选择不同的作业对应的方案也就不一样。

f2是执行的总时间。

#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
#define MAX 1001
#define max(x,y) ((x)>(y)?(x):(y))
int n=4;
int a[MAX]={0,5,12,4,8};
int b[MAX]={0,6,2,14,7};
int bestf;
int f1;
int f2[MAX];
int x[MAX];
int bestx[MAX];
void swap(int &x,int &y){
	int tmp=x;
	x=y;y=tmp;
}
void dfs(int i){
	if(i>n){
		if(f2[n]<bestf) {
			bestf=f2[n];
			for(int j=1;j<=n;j++){
				bestx[j]=x[j];
			}
		}
	}
	else {
		for(int j=i;j<=n;j++){
			swap(x[i],x[j]);
			f1+=a[x[i]];
			f2[i]=max(f1,f2[i-1])+b[x[i]];
			if(f2[i]<bestf)
			    dfs(i+1);
			f1-=a[x[i]];
			swap(x[i],x[j]);
		}
	}
} 
int main(){
	f1=0;
	bestf=INF;
	memset(f2,0,sizeof(f2));
	for(int k=1;k<=n;k++){
		x[k]=k;
	}
	dfs(1);
	printf("最少时间: %d , 最优调度方案 : ",bestf);
	for(int j=1;j<=n;j++){
		printf("%d ",bestx[j]);
	}
	printf("\n");
}

采用下界函数进行剪枝,仍然超时,时间复杂度O(n!) .

int bound(int i){
	int sum=0;
	for(int j=1;j<=i;j++){
		sum+=b[x[j]];
	}
	return f2[i]+tot-sum;
}
void dfs(int i){
	if(i>n){
		if(f2[n]<bestf) {
			bestf=f2[n];
			for(int j=1;j<=n;j++){
				bestx[j]=x[j];
			}
		}
	}
	else {
		for(int j=i;j<=n;j++){
			swap(x[i],x[j]);
			f1+=a[x[i]];
			f2[i]=max(f1,f2[i-1])+b[x[i]];
			if(bound(i)<bestf) dfs(i+1);
			f1-=a[x[i]];
			swap(x[i],x[j]);
		}
	}
}

2.活动安排问题仍为排列树

#include<stdio.h>
#define MAX 51
struct Action {
	int b;
	int e;
};
int n=4;
Action A[]={{0,0},{1,3},{2,5},{4,8},{6,10}};

int x[MAX];
int bestx[MAX];
int laste=0;
int sum=0;
int maxsum=0;

void swap(int &x,int &y){
	int tmp=x;
	x=y;y=tmp;
}
void dispasolution(){
	printf("最优调度方案:\n");
	int laste=0;
	for(int j=1;j<=n;j++){
		if(A[bestx[j]].b>=laste){
			printf("选取活动%d: [%d,%d)\n",bestx[j],A[bestx[j]].b,A[bestx[j]].e);
			laste=A[bestx[j]].e;
		}
	}
	printf("安排活动的个数= %d\n",maxsum);
}
void dfs(int i){
	if(i>n){
		if(sum>maxsum){
			maxsum=sum;
			for(int k=1;k<=n;k++){
				bestx[k]=x[k];
			}
		}
	}
	else {
		for(int j=i;j<=n;j++){
			swap(x[i],x[j]);
			int sum1=sum;
			int laste1=laste;
			if(A[x[j]].b>=laste){
				sum++;
				laste=A[x[j]].e;
			}
			dfs(i+1);
			swap(x[i],x[j]);
			sum=sum1;
			laste=laste1;
		}
	}
}
int main(){
	for(int i=1;i<=n;i++){
		x[i]=i;
	}
	dfs(1);
	dispasolution();
}

3,采用优先队列式分支限界法求解

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值