第一题:P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目解析:使用优先级队列(实现小根堆) 每次取前面两个堆 再存回去一个 直到不够两个
package 蓝桥算法训练__提高组.Day1;
import java.io.*;
import java.util.*;
/**
* @author snippet
* @data 2023-02-05 to 2023-02-20
* P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
*/
// 贪心 优先级队列
public class T1 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
static int n,ans;// n表示果子的个数 ans表示最小体力消耗值
static int[] a = new int[10100];// 数组a存采摘果子i需要的体力值
static Queue<Integer> q = new PriorityQueue<>();// 优先级队列(堆)每次取堆最前面两个数据
public static void main(String[] args) throws IOException {
n = nextInt();
for (int i = 0; i < n; i++) {
a[i] = nextInt();
q.offer(a[i]);
}
while (q.size() > 1){
int a = q.poll();
int b = q.poll();
ans += a+b;
q.offer(a+b);
}
pw.println(ans);
pw.flush();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}
![](https://img-blog.csdnimg.cn/img_convert/4ac63ddf7cd290f0013f302c34a1c6ea.png)
第二题:P1550 [USACO08OCT]Watering Hole G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目解析:找到田开井或田连田之间的最小价值 也就是最小生成树 用prim算法实现
package 蓝桥算法训练__提高组.Day1;
import java.io.*;
/**
* @author snippet
* @data 2023-02-05 to 2023-02-20
* P1550 [USACO08OCT]Watering Hole G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
*/
// 最小生成树(prim算法实现)
public class T2 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
static int n;// n表示田的行和列
static int INF = 0x3f3f3f3f;
static int N = 310;
static int[][] cost = new int[N][N];// // 二维数组cost 第一行存 每个田开井的价钱 1-n行存 i,j两个田连通的价钱
static int[] mincost = new int[N];// 一维数组mincost存i田的开井/井连通的最小价钱
static boolean[] used = new boolean[N];// 一维数组used存i田是否能通水了
/**
* prime算法
* @return 返回最小生成树的值 也就是 最小费用
*/
static int prim() {
// 初始化
mincost[0] = 0;
int ans = 0;
while (true) {
int t = -1;
for (int i = 0; i <= n; ++i) {
if (!used[i] && (t == -1 || mincost[i] < mincost[t])) {
t = i;
}
}
if (t == -1) break;
if (mincost[t] == INF) return INF;
// 标记i位置的农田已经通水
used[t] = true;
ans += mincost[t];
for (int i = 0; i <= n; ++i) {
mincost[i] = Math.min(mincost[i], cost[i][t]);
}
}
return ans;
}
public static void main(String[] args) throws IOException {
n = nextInt();
// 赋初始值
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cost[i][j] = INF;
mincost[i] = INF;
}
}
// 第一行存 每个田开井的价钱
// 1-n行存 i,j两个田连通的价钱
for (int i = 0; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int k = nextInt();
cost[i][j] = cost[j][i] = k;
}
}
pw.println(prim());
pw.flush();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}
![](https://img-blog.csdnimg.cn/img_convert/a762eca7f91dbf19aad280515f458139.png)
第三题:P1417 烹调方案 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目解析:这个题考01背包 但是它不能直接用01背包实现 因为i的价值是会根据t改变的 所以需要进行比较再排列
根据比较发现排序的时候需要满足cx*by<cy*bx
package 蓝桥算法训练__提高组.Day1;
import java.io.*;
import java.util.Arrays;
/**
* @author snippet
* @data 2023-02-05 to 2023-02-20
* P1417 烹调方案 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
*/
// 01背包
// 平常做01背包的题时,由于i的价值永远是不变的,所以i讨论的顺序对结果不影响
// 注意dp的先后顺序 注意价值的变化
public class T3 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
static int T,n;// T存总的最大时间 n存食材个数
// 十年 OI 一场空 不开long long见祖宗
static long ans;
// 二维数组arr 第一列存a 第二列存b 第三列存c表示该食材要的时间
// ai-t*bi表示美味指数
static long[][] arr = new long[55][3];
static long[] dp = new long[100100];
public static void main(String[] args) throws IOException {
T = nextInt();
n = nextInt();
for (int i = 0; i < n; i++) {
arr[i][0] = nextInt();
}
for (int i = 0; i < n; i++) {
arr[i][1] = nextInt();
}
for (int i = 0; i < n; i++) {
arr[i][2] = nextInt();
}
// 因为时间t的改变则美味指数会改变
// 需要满足cx*by<cy*bx
// 根据Arrays.sort的比较规则
// 则表示为cx*by-cy*bx
Arrays.sort(arr, ((a,b)->{
return (int) (a[2]*b[1]-b[2]*a[1]);
}));
// 01背包的实现
for (int i = 0; i < n; i++) {
for (int j = T; j >= arr[i][2]; j--) {
dp[j] = Math.max(dp[j], dp[(int)(j-arr[i][2])] + (arr[i][0]-j*arr[i][1]));
ans = Math.max(ans, dp[j]);
}
}
pw.println(ans);
pw.flush();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
}
![](https://img-blog.csdnimg.cn/img_convert/5976fc1e44e4ade9ee37d1913db8977f.png)
第四题:P1265 公路修建 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目解析:求多点间修公路时所有公路和的最短长度 连通所有城市 也就是最小生成树(用prim算法)
import java.io.*;
/**
* @author snippet
* @data 2023-02-05 to 2023-02-20
* P1265 公路修建 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
*/
// 最小生成树(prim算法)
public class T4 {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st = new StreamTokenizer(br);
static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
static int n;
static int INF = 0x3f3f3f3f;
static int N = 5050;
static double[][] cost = new double[N][2];// 二维数组cost的第一列存坐标的x 第二列存坐标的y
static double[] mincost = new double[N];// 一维数组mincost存这个点到其他点的最小距离
static boolean[] used = new boolean[N];// 一维数组used存该点是否被遍历过
// 算两点间距离
static double getcost(int x, int y) {
return Math.sqrt(Math.pow(cost[x][0]-cost[y][0], 2.0) + Math.pow(cost[x][1]-cost[y][1], 2.0));
}
/**
* 最小生成树 prim算法
* @return 最短的公路路径和
*/
static double prim() {
// 初始化
mincost[1] = 0;
double ans = 0;
while (true) {
int t = -1;
for (int i = 1; i <= n; ++i) {
if (!used[i] && (t == -1 || mincost[i] < mincost[t])) {
t = i;
}
}
if (t == -1) break;
if (mincost[t] == INF) return INF;
// 记录该点已经被遍历过了
used[t] = true;
ans += mincost[t];
for (int i = 1; i <= n; ++i) {
if (!used[i]) {
mincost[i] = Math.min(mincost[i], getcost(t,i));
}
}
}
return ans;
}
public static void main(String[] args) throws IOException {
n = nextInt();
// 赋初始值
for (int i = 1; i <= n; i++) {
mincost[i] = INF;
}
for (int i = 1; i <= n; i++) {
cost[i][0] = nextDouble();
cost[i][1] = nextDouble();
}
pw.printf("%.2f", prim());
pw.flush();
}
static int nextInt() throws IOException {
st.nextToken();
return (int)st.nval;
}
static double nextDouble() throws IOException {
st.nextToken();
return (double)st.nval;
}
}
![](https://img-blog.csdnimg.cn/img_convert/5f48839daa052fe072cb90746dc6e5bc.png)