题目描述
有 n 个人在一个水龙头前排队接水,假如每个人接水的时间为 Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。
输入格式
第一行为一个整数 nn。
第二行 n 个整数,第 i 个整数 Ti表示第 i 个人的等待时间 Ti
输出格式
输出文件有两行,第一行为一种平均时间最短的排队顺序;
第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。
输入输出样例
输入 #1
10
56 12 1 99 1000 234 33 55 99 812
输出 #1
3 2 7 8 1 4 9 6 10 5
291.90
说明/提示
n<=1000,ti<106,不保证ti不重复。
当ti 重复时,按照输入顺序即可(sort 是可以的)
此题代码已有其他博主发出,在此对原代码中自己不懂的地方进行了修改与注释,增加代码的易懂性,原帖贴在下面
原帖 >>请点这里<<
代码
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class P1223_ReceiveWater {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
p[] tt = new p[n];//抽象数组
for (int i = 0; i < tt.length; i++) {
tt[i] = new p();//给每个元素都定义为p对象
tt[i].o = i+1;//填序号
tt[i].t = sc.nextInt();//给“结构体”赋值时间
}
Arrays.sort(tt,new Comparator<p>() {
@Override
public int compare(p o1, p o2) {
// TODO Auto-generated method stub
//重写compare方法,按时间升序
return o1.t-o2.t;
}
});
long wait = 0;
long sum = 0;
for (int i = 0; i < tt.length; i++) {
System.out.print(tt[i].o+" ");
if (i>0) {//排除第1个人,否则i=0时 [i-1]数组越界
wait+=tt[i-1].t;
}
sum+=wait;
//System.out.println("i="+i+" , wait = "+wait+" , sum = "+sum+"");
//↑↑↑理解wait与sum的含义
/*
3 i=0 , wait = 0 , sum = 0
2 i=1 , wait = 1 , sum = 1
7 i=2 , wait = 13 , sum = 14
8 i=3 , wait = 46 , sum = 60
1 12 33 55
以前四个举例:
第一个人是3号,直接接水,等待时间和总等待都是0
第二个人是2号,接水时间12,等待时间是1,1即为第一个人接水时间
第三个人是7号,接水时间33,等待时间wait是前两个人接水时间1+12=13,
总等待sum是1+(1+12)=14,即上一个人的总等待时间加自己的等待时间
第四个人是8号,接水时间55,等待时间wait是前三个人接水时间1+12+33=46,
总等待sum是14+46=60,即上一个人的总等待时间加自己的等待时间
*/
}
System.out.println();
DecimalFormat df = new DecimalFormat("0.00");//按小数点后保留两位格式数据,也可使用prinf("%.2f",sum*1.0/n)
System.out.println(df.format(sum*1.0/n));//乘1.0是将sum转为float型,否则整型sum除以n会省略掉291.9后的“.9”
}
}
class p{//people人
int o;//order序号
int t;//time时间
}