算法:最佳调度问题(回溯法-解法)

最佳调度问题
【问题描述】        假设有n个任务由k个可并行工作的机器完成。完成任务i需要的时间为ti。试设计一个算法找出完成这n个任务的最佳调度,使得完成全部任务的时间最早。
【编程任务】        对任意给定的整数n和k,以及完成任务i需要的时间为ti,i=1~n。编程计算完成这n个任务的最佳调度。
【输入样例】 7  3 2  14  4  16  6  5  3
【输出样例】   17

即此问题为七个任务,三台机器。

首先列个七乘三的二维数组了解算法思路:

222
141414
444
161616
666
555
333

我们知道回溯法其实是穷举法加剪枝函数

我们的函数用到递归,层层返回。
《算法:最佳调度问题(回溯法-解法)》

解空间树为一颗n叉树,每搜索到叶子节点就更新一次bestp值(初值为INT_MAX),是用一次搜索结束后三个机器中花费时间最长的机器的所用时间作为此次分配的所用时间。

上图:红色为第一次分配;黄背景色为第二次;加粗字体为第三次;下划线为第四次。从上到下递归,然后层层返回。

贴个代码:

#include<iostream>
#include<algorithm>
#include<limit.h>
using namespace std;
int bestp=INT_MAX;
int *arr;
int *x;
int cp;
int n;//全局变量
void backtrack(int t,int k){
	if(t>n){//到达最后的值,叶子节点 
		int temp = INT_MIN; 
		for(int i = 1;i<=k;i++){
			if(x[i]>temp){
				temp = x[i];
			}
		}//求得当前路径k个机器的最大值temp ,temp是每求得一个路径,都要重新归零的。只是用来求得最大值的一个变量。 
		
		cp=temp;
		if(cp<bestp){
			bestp=cp;//每求得一个最大值,如果少于当前bestp,就更新一个一次bestp;			
		}
		return;
	}
	else {
		for(int i = 1;i<=k;i++){
			x[i]=x[i]+arr[t];
			if(x[i]<bestp){//如果加上此节点的值,此机器的时间已经大于bestp,就没必要往下面进行,剪枝。 
				backtrack(t+1,k);//递归下一层 
			}
			x[i]=x[i]-arr[t];//减去这一任务的值,恢复这一机器的x【i】,证明这一机器不要这一任务,就去找其他机器。 
		}		
	}
	
}

int main(){
	int m;
	int k;
	cin>>m;
	n=m;
	cin>>k;
	arr=new int[n+1];
	for(int i = 1;i<=n;i++){
		cin>>arr[i];
	}
	x = new int [k+1]();//某些acm网站测试平台可能不适用,如遇此种情况就写个循环初始化就好。	
	backtrack(1,k);
	cout<<bestp;
	system("pause");
	return 0;
	
}
点赞