非单位时间任务安排问题

算法设计与分析第二版(王晓东)

算法实现题4-18 非单位时间任务安排问题(习题4-15)

问题描述:
  具有截止时间和误时惩罚的任务安排问题可描述如下。
  (1) 给定n个任务的集合S={1,2,…,n};
  (2) 完成任务i 需要ti 时间,1 <= i <= n;
  (3) 任务i的截止时间i d ,1≤i≤n,即要求任务i在时间i d 之前结束;
  (4) 任务i 的误时惩罚i w ,1≤i≤n,即任务i 未在时间i d 之前结束将招致i w 的惩罚;
  若按时完成则无惩罚。
  任务安排问题要求确定S 的一个时间表(最优时间表)使得总误时惩罚达到最小。

编程任务:

  对于给定的n个任务,编程计算总误时惩罚最小的最优时间表。

数据输入:

  由文件input.txt给出输入数据。第1行是1 个正整数n,表示任务数。接下来的n行中,
  每行有3 个正整数a,b,c,表示完成相应任务需要时间a,截止时间为b,误时惩罚为c。

结果输出:
  将编程计算出的总误时惩罚输出到文件output.txt。
  输入文件示例 输出文件示例


input.txt 
7
1 4 70
2 2 60
1 4 50
1 3 40
1 1 30
1 4 20
3 6 80

output.txt
110

 

算法动态规划的实现:

  环境:VS2010, 使用语言: C++

  

/*****************************************************************************
File name: task_dynamic
Description: 用于解决非单位时间任务安排问题
Author: MadShaw
Version: 0.1
Date: 2014/11/10
History: 

    输入文件,第一行,表示有多少组数据,第二行 N 表示任务数,接下来 N 行中,每行有3个正整数 a, b, c,
    分别表示完成相应任务需要时间 a,截止时间 b,误时惩罚 c。
    
    1
    7
    1 4 70
    2 2 60
    1 4 50
    1 3 40
    1 1 30
    1 4 20
    3 6 80
*****************************************************************************/

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;
#define inf 655535


struct task{
    int time;
    int deadline;
    int cost;
};


/****************************************************************************
 Function:      cmp
 Description:   作为调用STL的sort函数的比较因子
 Calls:            无
 Called By:        sort,sort 由 init 调用
 Input:            const struct task &one        比较的第一个数 
                const struct task &other    比较的第二个数
 Output:        无
 Return:        0, 表示第一个数小于第二数    1,表示第一个数不小于第二个数
 Others:        无
 ***************************************************************************/
int cmp(const struct task &one , const struct task &other) { 
    return one.deadline < other.deadline; 
} 


/****************************************************************************
 Function:      init
 Description:   从文件中读取任务序列,将其存入vector中,并按任务的截止日期非降序
                排列,注意更改文件读取路径
 Calls:            cmp, sort
 Called By:        main
 Input:            vector<struct task> &job    任务序列
                vector< vector<int> > &map    最小误时惩罚表
                int &max_deadline            所有任务的最大截止时间
 Output:        无    
 Return:        无
 Others:        无
 ***************************************************************************/
void init(fstream &file, vector<struct task> &job, vector< vector<int> > &map, int &max_deadline){
    //fstream file;
    int lines=0;

    //file.open(path, ios::in);
    file >> lines;

    struct task one;
    for(int i=0; i<lines; i++){
        file >> one.time >> one.deadline >> one.cost;
        job.push_back(one);
    }

    sort(job.begin(), job.end(), cmp); 

    max_deadline = (job.at(job.size()-1)).deadline;
    map.resize(lines, vector<int>(max_deadline+1));
    
    for(int i=0; i<lines; i++){
        for(int j=0; j<max_deadline; j++){
            map[i][j] = inf;
        }
    }

    //file.close();
}

/****************************************************************************
 Function:      dynamic
 Description:   算法的动态规划部分
 Calls:            无
 Called By:        main
 Input:            vector<struct task> &job    任务序列
                vector< vector<int> > &map    最小误时惩罚表
                int &max_deadline            所有任务的最大截止时间
 Output:        已填写完成的最小误时惩罚表    
 Return:        无
 Others:        无
 ***************************************************************************/
void dynamic(vector<struct task> &job, vector< vector<int> > &map, const int &max_deadline){
    vector<struct task>::iterator iter = job.begin();
    
    for(; iter!=job.end(); iter++){
        cout<<(*iter).time<<" "<<(*iter).deadline<<" "<<(*iter).cost<<endl;
    }

    for(int i=0; i<= max_deadline; i++){
        if( job.at(0).time <= i ){
            map[0][i] = 0;
        }else{
            map[0][i] = job[0].cost;
        }
    }

    int cur_min = 0;
    int flag =0;

    for(int i=1; i<job.size(); i++){
        for(int j=0; j<=max_deadline; j++){
            flag =0;
            map[i][j] = map[i-1][j] + job.at(i).cost;
            cur_min = job.at(i).deadline > j ? j:job.at(i).deadline;

            if( ( cur_min >= job.at(i).time ) && ( map[i][j] > map[i-1][cur_min - job.at(i).time]) ){
                map[i][j] = map[i-1][cur_min - job.at(i).time];
                flag =1;
            }
        }
    }
    
}


/****************************************************************************
 Function:      read_map
 Description:   从动态规划的表中读取任务安排
 Calls:            无
 Called By:        main
 Input:            vector<struct task> &job    任务序列
                vector< vector<int> > &map    最小误时惩罚表
                int job_size                任务数
                int max_deadline            所有任务的最大截止时间
 Output:        及时任务安排表,误时任务安排表    
 Return:        无
 Others:        无
 ***************************************************************************/
void read_map(vector<struct task> &job, vector < vector<int> > &map, int job_size, int max_deadline){
    
    cout<<endl<<"最小误时惩罚:"<<map[job_size-1][max_deadline]<<endl;
    int job_id=0;
    int deadline=0;

    vector<bool> seq(job_size, true);
    

    job_id= job_size-1; 
    deadline = max_deadline;
    int first_punish = 0;
    int second_punish = 0;

    int min_deadline = 0;


    while( (job_id>=1) && (deadline>=0) ){

        first_punish = map[job_id-1][deadline] + job[job_id].cost;
        min_deadline = deadline > job[job_id].deadline ? job[job_id].deadline : deadline;

        if(deadline>0){
            second_punish = map[job_id-1][min_deadline - job[job_id].time];
        }

        if( deadline !=0 ){
            if(first_punish < second_punish){
        
                seq[job_id] = false;
        
            }else{
            
                deadline = min_deadline - job[job_id].time;
            }
        }else{
            if( first_punish ==  map[job_id][deadline]){
                seq[job_id] = false;
            }
        }

        job_id--;
    }
    
    //查找第一个及时任务
    int first_instance = 0;
    for(int i=1; i!=job.size(); i++){
        if(!seq[i]){
            first_instance = i;
            break;
        }
    }

    //确定第一个任务是否为误时任务
    int cur_time = 0;
    for(int i=first_instance; i!=job.size(); i++){
        cur_time += job[i].time;
        if( job[0].time + cur_time> job[i].deadline){
            seq[0] = false;
            break;
        }
    }

    cout<<endl<<"及时任务:"<<endl;
    for(int i=0; i!=job.size(); i++){
        if(seq[i]){
            cout<<job[i].time<<" "<<job[i].deadline<<" "<<job[i].cost<<endl;
        }
    }

    cout<<"已误时任务:"<<endl;
    
    for(int i=0; i!=job.size(); i++){
        if(!seq[i]){
            cout<<job[i].time<<" "<<job[i].deadline<<" "<<job[i].cost<<endl;
        }
    }
}


int main(){
    vector<struct task> job;
    vector < vector<int> > map;
    int max_deadline=0;
    string path="C:\\Users\\MadShaw\\Desktop\\input.txt";
    
    int count = 0;
    fstream file;
    file.open(path, ios::in);
    file >> count;

    for(int i=0; i<count; i++){
        cout<<"***********第"<<i+1<<"组数据********"<<endl<<endl;
        init(file, job, map, max_deadline);
        dynamic(job, map, max_deadline);
        read_map(job, map, job.size(), max_deadline);
        cout<<endl;
        job.clear();
        map.clear();
    }
    
    file.close();
    system("pause");
    return 0;
}

 

时空复杂度:

 

posted @ 2014-11-18 11:09  Madshaw  阅读(1943)  评论(0)    收藏  举报