算法学习系列(贪心算法)—多处最优服务次序问题

问题描述:
设有n(1≤n≤100)个顾客同时等待一项服务。顾客i需要的服务时间为ti,1≤i≤n,共有s处提供此服务。应如何安排n个顾客的服务次序才能使平均等待时间达到最小。平均等待时间是n个顾客的等待时间(含服务时间)总和除以n。编写一个贪心算法,计算n个顾客的最小平均等待时间及各处的顾客服务次序。
提示:
谈心策略:最短服务时间优先。

输入数据:
第一行,顾客数n及服务处数s,用空格分隔;
第二行开始的n行,每行描述一个顾客,每行两个数,分别是顾客号及他需要的服务时间,用空格分隔。
输出数据
第一行,平均等待时间;
第二行开始的s行,每行描述1处,第1个数为服务处编号,其后为按服务次序先后给出的顾客号,由空格分隔;

算法思想:
算法思想:
该算法使用贪心思想,贪心策略是客户按服务时间长短决定被服务次序,服务时间短的优先被服务,且前往下一个最快能结束服务的服务点
接受服务。
1、定义一个time数组记录每个服务点目前的时间,每服务一个客户time[服务点号]加上该客户的服务时间。
2、随后对每个服务点的目前时间进行比较,数值最小的服务点即为最快能接受服务的服务点,该服务点进行服务,
该客户的等待时间waited_time即为该服务点的目前时间time[服务点号],并记录好该客户接受服务的服务点号served_point
3、将每个用户的等待时间相加,再除以客户的总数,即得到平均服务时间

头文件代码:
定义了一个类、声明了用到的各个成员变量,公有的service函数是调用贪心算法的入口
MultiService.h:

#ifndef MULTISERVICE_H_INCLUDED
#define MULTISERVICE_H_INCLUDED

#include<iostream>
#include<fstream>
#include<malloc.h>

using namespace std;

class MultiService
{
    typedef struct Custom
    {
        int number;
        float service_time;     //该客户需要的服务时间
        float waited_time;      //该客户已经等待的时间
        int served_point;     //记录该客户被服务的服务处的编号
    }Custom ,*Customs;        //定义结构体数组,记录一个顾客的编号以及服务时间

    Customs customs;

    int custom_number;  //顾客的数量,从文件中读取
    int service_number; //服务处的数量,从文件处读取

    ofstream fout;

    void readFile(char *);

public:
    MultiService(char *in ,char *out);
    ~MultiService()
    {
        if(customs)
        {
            free(customs);
        }
        if(fout)
        {
            free(fout);
        }
    }
    void service();
};

#endif // MULTISERVICE_H_INCLUDED

cpp文件:
程序中所有的数据都从文件中读取、大家调用的时候请自己在同一目录下建立input.txt,其中输入数据为:

输入:
10 2
201 56
128 12
32 1
45 99
109 1000
88  234
69 33
120 55
50 99
48 812

MultiService.cpp:

#include "MultiService.h"

void MultiService::readFile(char *in)
{
    ifstream fin(in);

    if(!fin)
    {
        cout<<"File open error!"<<endl;
    }

    fin>>custom_number>>service_number;     //从文件中读取服务点数量以及客户数量

    customs = (Customs)malloc(sizeof(Custom) * custom_number);  //申请客户数量个客户的空间

    if(!customs)
    {
        cout<<"Memory malloc fail!"<<endl;
    }

    for(int i = 0 ;i<custom_number ;i++)
    {
        fin>>customs[i].number>>customs[i].service_time;        //从文件中读入用户的编号以及服务时间
    }
    fin.close();        //关闭文件
}

MultiService::MultiService(char *in ,char *out):fout(out)
{
    readFile(in);
}

void MultiService::service()
{
    for(int i = 0 ;i<custom_number ;i++)        //使用选择排序法按每个客户的service_time的大小次序进行排序
    {
        float min = customs[i].service_time;
        for(int j = i ;j<custom_number ;j++)
        {
            if(customs[j].service_time < min)
            {
                min = customs[j].service_time;
                Custom temp = customs[j];
                customs[j] = customs[i];
                customs[i] = temp;
            }
        }
    }

    float *time = (float *)malloc(sizeof(int ) * service_number);   //申请一个float类型的数组,记录该服务点的当前时间
    for(int i = 0 ;i<service_number ;i++)
    {
        time[i] = 0;        //初始化每个服务点的当前时间
    }

    int left_custom = custom_number;        //定义整型left_custom为客户目前的数目

    for(int i = 0 ;i<service_number ;i++)       //每个服务点开始服务第一个客户
    {
        customs[i].served_point = i;        //记录该客户被服务的服务点
        time[i] += customs[custom_number - (left_custom--)].service_time;   //该服务点的时间++
        customs[custom_number - left_custom - 1].waited_time = time[i];     //该用户的等待时间即为该服务点此时的时间
        //cout<<"time:"<<time[i]<<endl;
    }

    while(left_custom > 0)
    {
        int min = time[0];  //找到一个目前时间最短的,即是下一个能够接待客户的服务处
        int flag = 0;   //记录第几个服务处是下一个最快能接待客户的
        for(int i = 1 ;i<service_number ;i++)
        {
            if(time[i] < min )
            {
                min = time[i];
                flag = i;
            }
        }

        customs[custom_number - left_custom].served_point = flag;       //下一个最快能接待客户的服务点接待客户
                                                                        //并记录客户的服务点
        time[flag] += customs[custom_number - (left_custom--)].service_time;    //该服务点时间++
        customs[custom_number - left_custom -1].waited_time = time[flag];    //该用户的等待时间即为该服务点此时的时间
       // cout<<"time["<<flag<<"]:"<<time[flag]<<endl;
    }

    float time_sum = 0;
    for(int i = 0 ;i<service_number ;i++)       //输出每个服务点服务的客户编号
    {
        fout<<i + 1<<' ';
        for(int j = 0 ;j<custom_number ;j++)
        {
            if(customs[j].served_point == i)
            {
                fout<<customs[j].number<<' ';       //把每名顾客的编号输出到文件
            }
        }
        fout<<endl;
    }
    for(int i = 0 ;i<custom_number ;i++)        //将总服务时间相加
    {
        //cout<<customs[i].waited_time<<' ';
        time_sum += customs[i].waited_time;
    }

    fout<<time_sum/custom_number;   //得到平均服务时间

}


最后是主函数的调用入口

#include "MultiService.h"

int main()
{
    char *in = "input.txt";
    char *out = "output.txt";
    MultiService multi_service(in ,out);
    multi_service.service();
}

输出到文件中的最后结果为:

1 32 69 201 50 48
2 128 120 45 88 109
340
  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值