【洛谷】P1223 排队接水(java,排序,贪心)

题目描述

有 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时间
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值