批处理作业调度(回溯)

算法设计例题:批处理作业调度(回溯)

memory limit: 5000KB    time limit: 2000MS

accept: 1    submit: 12

Description

给定n个作业的集合 J = { J1,J2,…,Jn }。每一个作业Ji都有两项任务分别在两台机器上完成。每个作业必须先由机器1处理,然后由机器2处理。作业Ji需要机器j的处理时间为tji,其实 i=1,2,…,n,j=1,2。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。所有作业在机器2上完成处理的时间和称为该作业调度的完成时间和。
批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。
Input
输入的第一个为测试样例的个数T( T < 120 ),接下来有T个测试样例。每个测试样例的第一行是作业个数n( n <= 7 ),接下来n行,每行两个整数 t1i 和 t2i ,分别表示当前作业在机器1和机器2上的处理时间。( 0 <= t1i , t2i <= 100 )
Output
对应每个测试样例输出两行,第一行格式为"Case #: M",其中'#'表示第几个测试样例(从1开始计),M为最佳作业调度的时间和。第二行为n个以空格分隔的整数,表示最佳作业调度方案中各作业执行顺序的序号。
Sample Input
1
3
2 1
3 1
2 3
Sample Output
Case 1: 18
1 3 2



 算法分析:
这里有两台机器,如果将两台机器一起考虑的话,比较难解决。我们可以将只考虑一个问题,因为只要有一台机器处理作业的顺序确定了,另位一台处理作业的顺序也就确定了。将如第一台处理作业的顺序是1,3,2 那么第二台处理作业的顺序也就是1,3,2.在一台作业调度中,作业的顺序邮n! 中,(假设作业顺序是1,2,3)这很明显是一个排列数,当作业2在第一台机上处理时,第2台机器上可能也正在处理作业1,如果作业2处理完后,他有可能处理等待状况,只有第2台机器上的作业1被处理,作业2才能进入第一台机器,(傻子都懂).下面的数组开辟可能有出入,大家注意。



#include"iostream"
using namespace std ;
class FlowShop {  
public :
    int n ; //作业数
    int f1;//机器1完成处理时间
    int f;//完成时间之和
    int bestf;//当前最优值     
    int m[100][100] ; //各作业所需的处理时间    
    /*
     1 5 6
     2 5 7
    
     */
    int x[100];//当前作业调度
    int bestx[100];//当前最优作业调度
    int f2[100];//机器2完成处理时间
    void swap (int x [100] , int i , int  j )
    {
        int t = x[i];
        x[i] = x [j ] ;
        x[j] = t ;
    }
    void initilization()
    {
        f1 = 0 ;
        f = 0 ;
        bestf = 1000000 ;
        int i =0 ;
        
        while(i <=  99 )
        {
            x[i] = i ;
            i++;    
            ///一定要做这一步。
            f2[i] = 0 ;
            bestx[i] =  0 ;    
        }
        
    }
    void backtrack(int i )
    {
      if(i>n)
      {
        for(int j = 1 ; j <= n ; j++ )
          bestx[j]=x[j];
        bestf = f ;
      //  cout<< "++++"<<f<<endl;
      }
      
      else{
      
        for(int j = i ; j <= n ; j++ )
        {
          //f1处理机在完成第j作业的时间 = 第一j之前作业和第j作业所需的时间
          f1+=m[ x[j] ][ 1 ] ;
          
          //f2
        //如果算法没对f2[]初始化将会出错,因为i=1是,f2[i-1] = f2[0],f2[0]在没初始化时可能会出错
           f2[i] = ( ( f2[i-1]  > f1 ) ? f2[i-1]:f1 ) + m [ x [j] ] [ 2 ];
          //f2[j] = ( ( f2[i-1]  > f1 ) ? f2[i-1]:f1 ) + m [ x [j] ] [ 2 ];
          //完成时间之和*/
        
          f+=f2[i];
          
          if(f<bestf){
          
        swap (x,i,j);
        backtrack(i+1);
        swap(x,i,j);
          }
          
          f1 -= m[ x[ j ]] [1] ;
          f -= f2 [ i ] ;
          
        }
        
      }
    }
};


int main(){
 
  int T ;
    FlowShop fs ;
  cin>>T;
  int j =1 ;
    while(T>0)
    {
        cin>>fs.n;
        int i = 1 ;
        while( i <= fs.n )
        {
            cin>>fs.m[i][1];
            cin>>fs.m[i][2];
        //    cout<<fs.m[i][1]<<" "<<fs.m[i][2]<<endl;
            i++;
        }
        fs.initilization();
        fs.backtrack(1);
        i  = 1 ;
        cout<<"Case "<<j<<": "<<fs.bestf<<endl;
        while(i <= fs.n )
        {
            cout<<fs.bestx[i]<<" " ;
            i++;
            
        }
        cout<<endl;
        j++;
        T--;
        
    }
 
 
 
  return  0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值