试题 算法提高 搬运冰块(贪心 Java)

​​

问题描述
  丑枫接到了一份奇葩的工作:往冰库里搬运冰块.冰库外放着N箱冰块,由于室外温度高,冰块会很快融化,且每箱冰块的融化速度不同.因为每箱冰块的体积,质量不等,把每箱冰块搬运进冰块花费的时间也不同.因此需要合理安排搬运顺序,才能使总的冰块融化量最小.丑枫请你帮忙计算最少的总融化量是多少,以便汇报上司.

输入格式
第一行输入整数N   
接下来N行,每行两个整数,分别表示每箱冰块的搬运耗时Ti及融化速度Di.

输出格式

输出最少的总融化量

样例输入

6
6 1
4 5
4 3
6 2
8 1
2 6

样例输出

86
数据规模和约定
2<=N<=100000,1<=Ti<=4000000,1<=Di<=100
样例说明
按照6、2、3、4、1、5的顺序搬运
题目链接搬运冰块

分析:

  1. 首先理解题意, 根据样例输出可以得出,每块冰块在搬运途中不会融化,这一点是需要注意到的。若计算时,让它运送时也融化,就不能AC。
  2. 每个冰块有两个属性,搬运耗时和融化速度,所以我们可以定义一个冰块类,方便后面的计算。
  3. 贪心问题一般会选择恰当的顺序去计算结果,那么我们就要去进行排序,怎么排序呢?根据题意,就是去找最小消耗的顺序。对于任意两个冰块a,b,若先运送冰块a,冰块b消耗为10,然而先运送冰块b,a的消耗为5,那么就要先运送b,再运送a。
  4. 我们可以用Arrays.sort(数组,比较器) 的方法去排序,去new一个Comparator比较器,自定义实现它的compare方法。
	 Arrays.sort(ices,new Comparator<Ice>() {//ices是冰块数组
		@Override
		public int compare(Ice o1, Ice o2) {//t是搬运耗时,v是融化速度
			return o1.t*o2.v - o2.t*o1.v ;
		}
	});

补充:若compare方法返回值大于1,表示o1和o2需要交换,返回0或者小于0则不需要交换

代码(含注释):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
public class Main {
	public static void main(String[] args) throws Exception {
		//BufferdReader读取效率比Scanner快,对于数据量较大的可以采用BufferdReader
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(reader.readLine());
		Ice[] ices = new Ice[n];
		String[] tmp = null;
		for (int i = 0; i < n; i++) {
			tmp = reader.readLine().split(" ");//读取每一行的融化耗时和融化速度
			int t = Integer.parseInt(tmp[0]), v = Integer.parseInt(tmp[1]);
			ices[i] = new Ice(t, v);//对ices数组每个Ice对象实例化并赋值
		}
		Arrays.sort(ices,new Comparator<Ice>() {//自定义比较器
			@Override
			public int compare(Ice o1, Ice o2) {
				return o1.t*o2.v - o2.t*o1.v ;
			}
		});
		int time = 0;//消耗时间
		long cost = 0;//总融化量,根据题目的数据范围可知,必须用long型
		for(Ice ice : ices) {
			//每一块融化量是 运送前面所有冰块的耗时 * 当前冰块的融化速度
			cost += time * ice.v;
			time += ice.t;	//运送一块,消耗时间就要加上运送它的耗时,便于计算下一块的消耗
		}
		System.out.println(cost);
	}
}
class Ice{//冰块类
	int t, v;	//搬运耗时, 融化速度
	public Ice(int t, int v) {//构造方法
		this.t = t;
		this.v = v;
	}
}

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Easenyang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值