蓝桥算法训练__提高组.Day1

第一题: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;
    }
}

第二题: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;
    }
}

第三题: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;
    }
}

第四题: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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值