惠州一中博客欢迎您
   
 
 
排队接水
[ 2007-1-20 15:32:00 | By: yang ]
 

排队接水

源程序名            water.???pas, c, cpp

可执行文件名        water.exe

输入文件名         water.in

输出文件名          water.out

【问题描述】

    n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。

【输入】

    输入文件共两行,第一行为n;第二行分别表示第1个人到第n个人每人的接水时间T1T2,…,Tn,每个数据之间有1个空格。

【输出】

    输出文件有两行,第一行为一种排队顺序,即1n的一种排列;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)

【样例】

       water.in                                                    water.out

       10                                                            3 2 7 8 1 4 9 6 10 5

       56 12 1 99 1000 234 33 55 99 812                     532.00(改之前:291.90)

【算法分析】

       平均等待时间是每个人的等待时间之和再除以n,因为n是一个常数,所以等待时间之和最小,也就是平均等待时间最小。假设是按照1~n的自然顺序排列的,则这个问题就是求以下公式的最小值:

       如果用穷举的方法求解,就需要我们产生n个人的所有不同排列,然后计算每种排列所需要等待的时间之和,再“打擂台”得到最小值,但这种方法需要进行n!次求和以及判断,时间复杂度很差!

       其实,我们认真研究一下上面的公式,发现可以改写成如下形式:

       这个公式何时取最小值呢?对于任意一种排列k1, k2, k3, , kn,当≤…≤时,total取到最小值。如何证明呢?方法如下:

       因为

       假设i<j,而<,这时的和为total1,而把kikj互换位置,设新的和为total2,则:

      

       我们发现上述△total恒大于0,所以也说明了任何次序的改变,都会导致等待时间的增加。从而证明了我们的设想。

       既然如此,我们就得到了一种最贪心的策略:把接水时间少的人尽可能排在前面。这样一来,问题的本质就变成:把n个等待时间按非递减顺序排列,输出这种排列,并求出这种排列下的平均等待时间。

 

C语言代码:


#i nclude <stdio.h>

#define N 100/*假设最大数据量为100*/

int main()

{

       int T[N],/*接受输入数据*/

              sort[N],/*记录排序前的位置*/

              n=0,/*数据个数*/

              i,j,/*循环量*/

              time=0,/*总等待时间*/

              count=0;/*记录个数*/

      

       FILE *in,*out;

      

       in=fopen("water.in","r");

       /*输入*/

       fscanf(in,"%d",&n);

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

       {

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

       }

       /*初始化,开始所记录的位置为-1*/

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

       {

              sort[i]=-1;

       }

       /*sort排序*/

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

       {

              count=0;

              for(j=0;j<n;j++)

              {

                     if(T[i]>T[j])count++;/*记录比T[i]小的数的个数*/

              }

              while(sort[count]!=-1)count++;/*注意有相同的数的情况,则位置要相应后移*/

              sort[count]=i;/*记录T[i]sort的位置*/   

       }

 

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

       {

              time+=(n-i)*T[sort[i]];/*累加等待时间*/

       }

       /*输出*/

       out=fopen("water.out","w");

      

       fprintf(out,"%d",sort[0]+1);

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

       {

              fprintf(out," %d",sort[i]+1);

       }

       fprintf(out,"\n%.2f",time*1.0/n);

      

       fclose(in);

       fclose(out);

}


 

 
 
  • 标签:贪心法 C语言 
  • 发表评论:

      大名:
      密码:
      主页:
      标题:
      惠州一中博客欢迎您
     
    惠州一中博客欢迎您

    惠州一中博客欢迎您

    时 间 记 忆
    惠州一中博客欢迎您

    最 新 评 论
    惠州一中博客欢迎您

    最 新 日 志
    惠州一中博客欢迎您
    最 新 留 言
    惠州一中博客欢迎您

    搜 索

    用 户 登 录

    友 情 连 接

    模板设计:老鹰

    惠州一中博客欢迎您


     
    ""老鹰""