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;
}