问题描述
小明想从A徒步到B,总路程需要M天,路程中为了确保安全,小明每天需要消耗1份食物。
在起点及路程当中,零星分布着N个补给站,可以补充食物,不同补给站的食物价格可能不同。
请问小明若要安全完成徒步,最少需要花费多少钱呢?
输入格式
第一行为两个正整数M、N,代表总路程M天,补给站个数N
接下来N行,每行有两个非负整数A、B代表一个补给站,表示第A天经过该补给站,每份食物的价格为B元。
A是从0开始严格递增的,即起点一定有补给站,补给站是按位置顺序给出的,且同一个位置最多有一个补给站。
输出格式
输出一个整数,表示最少花费的金额
输入样例
5 4
0 2
1 3
2 1
3 2
输出样例
7
思路
好久没有做过这种贪心题目了,这道题如果按照题意去模拟计算那可真是麻烦坏了,如果从头开始按照题意去计算是很难得到正确的答案的
本题要求最小的花费,每个补给站的价格不一样,所以我们直接寻找价格最低的补给站去购买尽可能多的食物,这个时候就不能从头开始走了,我们要从终点向起点走,因为对于价格最低的商店我们买了它的食物只能在他的后面食用,就像上面那个样例,我们在2号补给站购买足以到终点的实物,然后找价格第二低的补给站购买足够的实物,直到走到起点
首先,按照食物价格从低到高对这个二维数组进行排序。
接着,从价格最低的那个补给站开始进行购买食物的操作,所购买的食物数量要足以确保能够到达终点。与此同时,将终点的坐标设置为这个价格最低的补给站的坐标。
然后,在从前往后遍历这个二维数组的过程中进行如下判断:
如果补给站的坐标小于终点坐标,那么就再次执行前面所说的从价格最低的补给站购买足以到达终点的食物以及将终点坐标设置为该补给站坐标的操作;如果补给站的坐标大于终点坐标,那么就直接跳过这个补给站,不进行任何操作。像这样,在遍历完一遍这个二维数组之后,就能够得到最终的答案了。
` public static int solution(int m, int n, int[][] p) {
//先对补给站按照食物价格从低到高排序
Arrays.sort(p,new Comparator<int[] >() {
public int compare(int[] a,int[] b){
return a[1]-b[1];
}
});
int res=0;
for(int[] x:p){
//如果补给站在终点后面直接跳过
if(x[0]>=m){
continue;
}
res+=(m-x[0])*x[1];//购买足以到终点的实物
m=x[0];//更新终点坐标
}
return res;
}`
对于这类题目,如果按照正常的思维去模拟的话是很难写出正解的,可是只要察觉到了它的贪心之处我们就可以轻松的解决,往往贪心题目中都要求求出最小次数之类的答案,同时需要利用排序辅助计算。