打水问题

2040: 打水问题

时间限制: 1 Sec  内存限制: 512 MB
提交: 123  解决: 59
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

N个人要打水,有M个水龙头,第i个人打水所需时间为Ti,请安排一个合理的方案使得所有人的等待时间之和尽量小。

 

输入

第一行两个正整数N  M  接下来一行N个正整数Ti。 
N,M< =1000,Ti< =1000 

 

输出

最小的等待时间之和。(不需要输出具体的安排方案) 

 

样例输入

7 3
3 6 1 4 2 5 7

 

样例输出

11

 

提示

一种最佳打水方案是,将N个人按照Ti从小到大的顺序依次分配到M个龙头打水。
例如样例中,Ti从小到大排序为1,2,3,4,5,6,7将他们依次分配到3个龙头,则去龙头一打水的为1,4,7;去龙头二打水的为2,5;去第三个龙头打水的为3,6。
第一个龙头打水的人总等待时间=0+1+(1+4)=6
第二个龙头打水的人总等待时间=0+2=2
第三个龙头打水的人总等待时间=0+3=3
所以总的等待时间=6+2+3=11

 

来源/分类

算法提高 

 

思路:

按照题目中给出的提示进行编写,

#include<stdio.h>
int main()
{
    int n,m,t;
    scanf("%d%d",&n,&m);
    int a[n];
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);// 输入每个人的打水时间     
    for(int i=0;i<n;i++)
        for(int j=0;j<i;j++)
        {
            if(a[i]<a[j])
            {
                t=a[i];
                a[i]=a[j];
                a[j]=t;
            }//将打水时间由小到大排序 
        }
    //用一个二维数组b[][]将要打水的人分成m组,每组站一列 
    if(n%m==0)  t=0;
    else t=1;
    int k=0,line=n/m+t;//如果n对m取余不为零,需要另外加一行 
    int b[line][m];
    int sum1=0,sum2=0,sum3=0;
    //为b[][]赋值 ,分为完整的line行m列数组和不完整的 
    /*  例如  完整的:1 2 3
                      4 5 6
                      7 8 9
                      
                      
            不完整的  1 2 3
                      4 5 6
                      7   有两列不完整
    */ 
    if(n%m!=0)//不完整的队列 
    {
    //完整的前line-1行 
    for(int i=0;i<line-1;i++)
        for(int j=0;j<m;j++)
            b[i][j]=a[k++];
    //缺少元素的最后一行 
    for(int i=0;i<n%m;i++)
        b[line-1][i]=a[k++];
    //计算前n%m列总的等待时间,这几列是完整的    
    for(int i=0;i<n%m;i++)
        {            
            for(int j=0;j<line;j++)
            {
                for(int k=0;k<j;k++)
                {
                    sum1+=b[k][i];//每个人各自的等待时间 
                }
                sum2+=sum1;//每一列的等待时间 
                sum1=0;//归零以便下次使用 
            }
            sum3+=sum2;//总的等待时间 
            sum2=0;       
        }
    //计算剩余几列总的等待时间,他们各缺少一个元素 
    for(int i=n%m;i<m;i++)
        {            
            for(int j=0;j<line-1;j++)
            {
                for(int k=0;k<j;k++)
                {
                    sum1+=b[k][i];
                }
                sum2+=sum1;
                sum1=0;
            }
            sum3+=sum2;
            sum2=0;        
        }
    }
    else//完整的队列 
    {
        for(int i=0;i<line;i++)
            for(int j=0;j<m;j++)
                b[i][j]=a[k++];
        
        for(int i=0;i<m;i++)
        {            
            for(int j=0;j<line;j++)
            {
                for(int k=0;k<j;k++)
                {
                    sum1+=b[k][i];
                }
                sum2+=sum1;
                sum1=0;
            }
            sum3+=sum2;
            sum2=0;        
        }
    }
    printf("%d\n",sum3);//输出总的等待时间 
    return 0; 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值