最优服务次序C语言,最优服务次序问题 和 汽车加油问题

1. 最优服务次序问题

问题描述: 设有n个顾客同时等待一项服务。顾客i需要的服务时间为ti, 1≦i ≦n 。共有s处可以提供此服务。应如何安排n个顾客的服务次序才能使平均等待时间达到最小平均等待时间是n个顾客等待服务时间的总和除以n。

算法设计:对于给定的n个顾客需要的服务时间,计算最优服务次序。

数据输入:由文件input.txt给出输入数据。第一行是正整数n,表示有n个顾客。接下来的1行中,有n个正整数,表示n个顾客需要的服务时间。

结果输出:将计算的最小平均等待时间输出到文件output.txt中。

输入文件示例                                       输出文件示例

input.txt                                              output.txt

10                                                          532.00

56 12 1 99 1000 234 33 55 99 812

问题分析:假设原问题为T(先假设只有一个服务点),我们已知某个最优服务系列,即最优解为 A={t(1),t(2),….t(n)} (其中t(i)为第i个用户需要的服务时间),则每个用户等待时间为: T(1)=t(1);T(2)=t(1)+t(2);...T(n)=t(1)+t(2)+t(3)+…+t(n);则总等待时问,即最优值为:

TA=T(1)+T(2)+T(3)+...+T(n)=n*t(1)+(n-1)*t(2)+…+(n+1-j)*t(i)+…+2*t(n-1)+t(n);由于平均等待时间是n个顾客等待时间的总和除以n,故本题实际上就是求使顾客等待时间的总和最小的服务次序。

贪心策略: 最短服务时间优先,先将服务时间排序,然后注意后面的等待服务时间既包括等待部分,也包括服务部分。对服务时间最短的顾客先服务的贪心选择策略,首先对需要服务时间最短的顾客进行服务,即做完第一次选择后,原问题T变成了需对n-1个顾客服务的新问 题T'。新问题和原问题相同,只是问题规模由n减小为n-1。基于此种选择策略,对新问题T',选择n-1顾客中选择服务时间最短的先进行服务,如此进行 下去,直至所有服务都完成为止 。

算法实现:采用最短服务时间优先的贪心策略。首先将每个顾客所需要的服务时间从小到大排序。然后申请2个数组: st[]是服务数组,st[j]为第j个队列上的某一个顾客的等待时间;su[]是求和数组,su[j]的值为第j个队列上所有顾客的等待时间。

算法复杂性分析:程序主要是花费在对各顾客所需服务时间的排序和贪心算法,即计算平均服务时间上面。其中,贪心算法部分只有一重循环影响时间复杂度,其时间复杂度为O(n):而排序算法的时间复杂度为O(nlogn)。因此,综合来看算法的时间复杂度为O(nlogn)。

代码实现:

#include

#include

#include

using namespace std;

using std::vector;

double greedy(vectorx,int s){

vectorst(s+1,0);

vectorsu(s+1,0);

int n=x.size();

sort(x.begin(),x.end());

int i=0,j=0;

while(i

st[j]+=x[i];

su[j]+=st[j];

i++;

j++;

if(j==s)j=0;

}

double t=0;

for(i=0;i

t+=su[i];

t/=n;

return t;

}

int  main(){

int n;//等待服务的顾客人数

int s;//服务点的个数

int i;

int a;

int t;//平均服务时间

vectorx;

cout<

cin>>n;

cout<

cin>>s;

cout<

for(i=1;i<=n;i++){

cout<>a;   x.push_back(a);

}

t=greedy(x, s);

cout<

}

运行结果:

014f6225d8dacd81d2fda34c94527920.png

2. 汽车加油问题

问题描述:一辆汽车加满油后,可行使nkm。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油才能使加油次数最少。并证明算法产生一个最优解。

算法设计:对于给定的n和k个加油站位置,计算最少加油次数。

数据输入:由文件inpput.txt给出输入数据。第1行有2个正整数n和k,表示汽车加满油后可行驶nkm,且旅途中有k个加油站。接下来的1行中,有k+1个整数,表示第k个加油站与第k-1个加油站之间的距离。第0个加油站表示出发地,汽车已加满油。第k+1个加油站表示目的地。

结果输出:将计算的最少加油次数输出到文件output.txt.如果无法到达目的地,则输出”No Solution!”。

输入文件示例                          输出文件示例

input.txt                                output.txt

7 7                                             4

1 2 3 4 5 6 6

问题分析:有几种情况:设加油次数为k,每个加油站间距离为a[i];i=0,1,2,3……n

(1)始点到终点的距离小于n,则加油次数k=0。

(2)始点到终点的距离大于n。

A  加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n;

B  加油站间的距离相等,即a[i]=a[j]=L>N,则不可能到达终点;

C 加油站间的距离相等,即a[i]=a[j]=L

k=[n/N]+1(n%N!=0);

D  加油站间的距离不相等,即a[i]!=a[j],则加油次数k通过以下算法求解。

算法思路:汽车行驶过程中,应走到自己能走到并且离自己最远的那个加油站,在那个加油站加油后再按照同样的方法贪心。

算法实现:先检测各加油站之间的距离,若发现其中有一个距离大于汽车加满油能跑的距离,则输出no solution。否则,对加油站间的距离进行逐个扫描,尽量选择往远处走,不能走了就让num++,最终统计出来的num便是最少的加油站数。

算法复杂性分析:想要知道在哪个加油站加油必须遍历所有的加油站,且不需要重复遍历,所以时间复杂度问O(n)。

代码实现:

/*汽车加油问题

先检测各加油站之间的距离,若发现其中有一个距离大于汽车加满油能跑的距离,则输出no solution

否则,对加油站间的距离进行逐个扫描,尽量选择往远处走,不能走了就让num++,最终统计出来的num便是最少的加油站数

*/

#include

void greedy(int d[],int n,int k){

FILE *fp;

int num = 0;

for(int i = 0;i <= k;i++){

if(d[i] > n){

printf("no solution!其中有一个距离大于汽车加满油能跑的距离!\n");

return;

}

}

for(int i=0,s=0;i<=k;i++){

s += d[i];

if(s > n) {

num++;

s = d[i];

}

}

printf("最少加油次数为:%d\n",num);

fp=fopen("output.txt","w");

fprintf(fp,"%d",num);

}

int main(){

int i,n,k;

int d[1000];

FILE *fp;

fp=fopen("input.txt","r");

fscanf(fp,"%d%d",&n,&k);

printf("汽车加满油后可行驶: %d km\n旅途中加油站个数为: %d \n",n,k);

for(i=0;i<=k;i++)

fscanf(fp,"%d",&d[i]);

greedy(d,n,k);

fclose(fp);

return 0;

}

文件input.txt的内容(运行程序前):    output.txt内容(运行程序后):

71e218b422c16997a6ff44c66491bc4a.png    

5635c3c89768dc22a9cc8de14c4a0e07.png

运行结果:

7035341e786b6fcc3ad96899e1113050.png

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值