问题描述
丑枫接到了一份奇葩的工作:往冰库里搬运冰块.冰库外放着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的顺序搬运
题目链接:搬运冰块
分析:
- 首先理解题意, 根据样例输出可以得出,每块冰块在搬运途中不会融化,这一点是需要注意到的。若计算时,让它运送时也融化,就不能AC。
- 每个冰块有两个属性,搬运耗时和融化速度,所以我们可以定义一个冰块类,方便后面的计算。
- 贪心问题一般会选择恰当的顺序去计算结果,那么我们就要去进行排序,怎么排序呢?根据题意,就是去找最小消耗的顺序。对于任意两个冰块a,b,若先运送冰块a,冰块b消耗为10,然而先运送冰块b,a的消耗为5,那么就要先运送b,再运送a。
- 我们可以用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;
}
}