贪心法_多机调度问题

该博客探讨了如何使用贪心策略解决多机调度问题,这是一个NP完全问题。当作业数量小于或等于机器数量时,只需将作业分配给各自对应的时间区间。当作业数量大于机器数量时,按作业处理时间从大到小排序,依次分配给空闲的机器,以尽量缩短总的处理时间。博客提供了一个VC++.NET的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设有 n 个独立的作业 { 1 , 2 , .. , n },由 m 台相同的机器进行加工处理。
作业 i 所需的处理时间为 ti。现约定,任何作业可以在任何一台机器上加工处理,
但未完工前不允许中断处理。任何作业不能拆分成更小的作业。
多机调度问题要求给出一种作业调度方案,使所给的 n 个作业在尽可能短的时间内
由 m 台机器加工处理完成。

分析:
这个问题是一个NP完全问题,到目前为止还没有一个有效的解法。
对于这一类问题,用贪心选择策略有时可以设计出较好的近似算法。
采用最长处理时间作业优先的贪心选择策略可以设计出解多机调度问题的较好的近似算法。

按此策略,
当 n <= m 时,只要将机器 i 的[0,ti]时间区间分配给作业i即可。

当 n > m 时,首先将 n 个作业依其所需的处理时间从大到小排序。
 然后依此顺序将作业分配给空闲的处理机。

<<<< 简单一句话,让最空闲的机器做最繁重的任务 >>>>

// 以上问题与分析来自
// 《计算机算法设计与分析(第2版)》
// 电子工业出版社
// 以下程序为 zerodspace 源创


// 程序员: http://blog.youkuaiyun.com/zerodspace
// 时间: 20:46 2005-10-22
// 功能: 贪心法——多机调度问题
// 系统: VC++.NET Win32控制台项目


// machineWork.h
//
#pragma once

#define maxWork 100
#define maxMachine 100

class machineWork
{
public:
 machineWork(void);
 ~machineWork(void);

 void SetMachine( int machine );
 void SetWorks( double times[] , int works );
 bool Arrange();
 void Sort( int timeId[] );
 void Print();
private:
 //double times[maxWork];
 double timesUnsorted[maxWork];
 int graph[maxMachine][maxWork];
 double machinesTime[maxMachine];
 int machines;
 int works;
};


// machineWork.cpp
//
#include "StdAfx.h"
#include "./machinework.h"

machineWork::machineWork(void)
{
}

machineWork::~machineWork(void)
{
}
//
//
void machineWork::Sort( int timeId[] )
{
 for( int i = 0 ; i < works ; i++ )
  timeId[i] = i;
 for( int i = 0 ; i < works - 1 ; i++ )
 {
  double min = timesUnsorted[ timeId[i] ];
  int p = i;
  for( int j = i + 1 ; j < works ; j++ )
  {
   if( this->timesUnsorted[ timeId[j] ] > min )
   {
    min = this->timesUnsorted[ timeId[j] ];
    p = j;
   }
  }
  int t = timeId[i];
  timeId[i] = timeId[p];
  timeId[p] = t;
 }
}
//
//
void machineWork::SetMachine( int machines )
{
 this->machines = machines;
}
//
//
void machineWork::SetWorks( double times[] , int works )
{
 this->works = works;
 for( int i = 0 ; i < works ; i++ )
  timesUnsorted[i] = times[i];
}
//
//
bool machineWork::Arrange()
{
 int timeId[maxWork];
 Sort( timeId );
 //某一工作安排后,对机器的工作时间进行排序
 //index[i]保存机器编号
 int index[maxMachine];
 //graph[i][0]表示机器i中已经安排了几项任务
 for( int i = 0 ; i < machines ; i++ )
  graph[i][0] = 0;
 //机器已经安排的工作时间
 for( int i = 0 ; i < works ; i++ )
  machinesTime[ i ] = 0.0;
 //index[0]所指向的 graph[ index[0] ][0] 的值是最小的
 for( int i = 0 ; i < machines ; i++ )
  index[i] = i;
 //给 i 号作业分配机器
 for( int i = 0 ; i < works ; i++ )
 {
  //把作业分配给 index[0] 所指向的机器
  graph[ index[0] ][0]++;
  graph[ index[0] ][ graph[index[0]][0] ] = timeId[i];
  machinesTime[ index[0] ] += timesUnsorted[ timeId[i] ];
  //对机器的已经安排的工作时间进行排序
  int j = 0;
  while( j < machines - 1 && machinesTime[ index[ j ] ] > machinesTime[ index[ j+1 ] ] )
  {
   int t = index[j];
   index[j] = index[j+1];
   index[j+1] = t;
   j++;
  }
 }
 return true;
}
//
//
void machineWork::Print()
{
 printf( "----------------------------------------/n" );
 for( int i = 0 ; i < works ; i++ )
  printf( "工作 %d 所需要的时间 %5.f/n" , i , timesUnsorted[i] );
 printf( "/n" );


 for( int i = 0 ; i < machines && i < works ; i++ )
 {
  printf( "机器 %d 工作总时间 %.f = " , i , machinesTime[i] );
  printf( "%.f " , timesUnsorted[ graph[i][1] ] );
  for( int j = 2 ; j <= graph[i][0] ; j++ )
   printf( "+ %.f " , timesUnsorted[ graph[i][j] ] );
  printf( "/n" );
 }
 printf( "/n" );


 for( int i = 0 ; i < machines ; i++ )
 {
  printf( "机器 %d 上的工作安排 " , i );
  for( int j = 1 ; j <= graph[i][0] ; j++ )
   printf( "%d " , graph[i][j] );
  printf( "/n" );
 }
 printf( "----------------------------------------/n" );
}
//
//



// greedy.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "machineWork.h"
#include "conio.h"

int _tmain(int argc, _TCHAR* argv[])
{
 double t[maxWork] = { 2 , 14 , 4 , 16 , 6 , 5 , 3 };
 machineWork w;
 w.SetMachine( 10 );
 w.SetWorks( t , 7 );
 w.Arrange();

 w.Print();

 getch();
 return 0;
}


// 新建项目 win32控制台项目 greedy
// 添加 一般C++类 machineWork
// 写代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值