参考
【算法1-5】贪心 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
- P2240 【深基12.例1】部分背包问题
- P1223 排队接水
- P1803 凌乱的yyy / 线段覆盖
- P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
- P3817 小A的糖果
- P1106 删数问题
- P1478 陶陶摘苹果(升级版)
- P5019 [NOIP2018 提高组] 铺设道路
- P1208 [USACO1.3] 混合牛奶 Mixing Milk
- P1094 [NOIP2007 普及组] 纪念品分组
- P4995 跳跳!
- P4447 [AHOI2018初中组] 分组
- P1080 [NOIP2012 提高组] 国王游戏
题目
P2240 【深基12.例1】部分背包问题
这道题一开始0分,主要是浮点数精度问题、对list的大小判断防止越界
package _1_5;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class P2240 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int t = scanner.nextInt();
ArrayList<Jinbi> list = new ArrayList<>();
while (n-- > 0) {
int m = scanner.nextInt();
int v = scanner.nextInt();
list.add(new Jinbi(m, v));
}
if (n == 0 || t == 0) System.out.printf("%.2f", 0);
// algo 贪心:根据性价比排降序
list.sort(new Comparator<Jinbi>() {
@Override
public int compare(Jinbi o1, Jinbi o2) {
if (o1.mv > o2.mv) return -1;
else if (o1.mv == o2.mv) {
return 0;
} else return 1;
}
});
// 按顺序装满背包
double sum = 0;
// !注意还要判断还有没有金币可取,否则越界
while (t > 0 && list.size() > 0) {
Jinbi jinbi = list.get(0);
// 整个装得下
if (jinbi.m <= t) {
t -= jinbi.m;
sum += jinbi.v;
list.remove(0);
} else {
// 装不下,分割
sum += jinbi.mv * t;
break;
}
}
System.out.printf("%.2f", sum);
scanner.close();
}
}
class Jinbi {
double m;
double v;
double mv;
// !注意在计算性价比的时候需要用浮点数计算得出浮点数,否则使用int计算得出的浮点数精度不准确
// algo 浮点数精度:除法的比较可以转换成交叉相乘的比较
// 即 o1.v/o1.m > o2.v/o2.m <-> o1.v*o2.m > o2.v*o1.m 这样也可以避免精度问题
public Jinbi(double m, double v) {
this.m = m;
this.v = v;
this.mv = v / m;
}
}
P1803 凌乱的yyy / 线段覆盖
这道题我一开始想错了,按照了开始时间排序,应该按照结束时间排序
过了70%,剩余MLE
package _1_5;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class P1803 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine());
ArrayList<Bisai> list = new ArrayList<>();
while (n-- > 0) {
list.add(new Bisai(scanner.nextInt(), scanner.nextInt()));
}
// algo 贪心:按照结束时间升序排序
// 越早结束后面才能进行更多
list.sort((o1, o2) -> {
if (o1.end == o2.end) {
return (o1.end - o1.start) - (o2.end - o2.start);
} else {
return o1.end - o2.end;
}
});
int count = 0;
int time = 0;
for (Bisai bisai : list) {
if (bisai.start >= time) {
time = bisai.end;
count++;
}
}
System.out.println(count);
scanner.close();
}
}
class Bisai {
int start;
int end;
public Bisai(int start, int end) {
this.start = start;
this.end = end;
}
}
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
原来Java有自带的堆排序,那没事了(不过还是回顾了以下堆的实现,总的来说就是建堆:插入元素并且上浮;取元素:堆顶和最后一个元素交换并且下沉)
PriorityQueue优先队列
- 可以使用自定义类,但是要实现Comparable接口的compareTo方法;或者创建queue的时候传入Comparator的实现类。
- 默认小根堆,按顺序取值的话得到的是升序。
- 例如Integer包装类的compare是写死的,所以要实现Comparator
package _1_5;
import java.util.*;
public class P1090 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
// algo 堆排序/优先队列:https://blog.csdn.net/m0_56361048/article/details/127950384
PriorityQueue<Long> heap = new PriorityQueue<>();
while (n-- > 0) {
heap.offer((long) scanner.nextInt());
}
long count = 0;
while (heap.size() >= 2) {
Long a = heap.poll();
Long b = heap.poll();
Long c = a + b;
count += c;
heap.offer(c);
}
System.out.println(count);
scanner.close();
}
}
eap.poll();
Long c = a + b;
count += c;
heap.offer©;
}
System.out.println(count);
scanner.close();
}
}