AtCoder Beginner Contest 325 题解 A-E

A - Takahashi san

原题链接

题目描述
给你两个字符串,将第二个字符串改为san后与第一个字符串一起输出

public static void solve() throws IOException {
    String s1 = readString(), s2 = readString();
    printWriter.println(s1 + " " + "san");
}

B - World Meeting

原题链接

题目描述
一个公司有 N N N个基地,第 i i i个基地有 W i W_i Wi名员工,该基地所在区域的时间是 X i X_i Xi,现在你是公司老总,想要在 9 : 00 ∼ 18 : 00 9:00 \sim 18:00 9:0018:00 内开一个会议,要求让最多员工参会,求出这个员工数最多能是多少。

思路:模拟

  • 枚举时间偏移量 p p p ( 0 ∼ 23 0 \sim 23 023),再遍历 N N N个基地,求在 p p p的偏移量下能参会的最多员工。
public static void solve() throws IOException {
    int n = readInt();
    Pair[] pairs = new Pair[n + 1];
    for (int i = 1; i <= n; i++) {
        int a = readInt(), b = readInt();
        pairs[i] = new Pair(a, b);
    }
    long max = 0;
    for (int i = 0; i < 24; i++) {
        long cur = 0;
        for (int j = 1; j <= n; j++) {
            int t = (pairs[j].second + i) % 24;
            if (t >= 9 && t <= 17) cur += pairs[j].first;
        }
        max = Math.max(max, cur);
    }
    printWriter.println(max);
}

C - Sensors

原题链接

题目描述
有一个 n n n m m m列的二维网格,网格的部分点上有传感器,传感器会向自己相邻的 8 8 8个方向上的点传染,如果两个传感器相邻,那么他们发挥的作用等于一个传感器,求出最终发挥作用的传感器有多少个。

思路:深度优先搜索

  • 遍历每一个未被遍历过的传感器,让其不断向自己相邻的传感器传染。
static char[][] map;
static boolean[][] vis;
static int n, m;

public static void solve() throws IOException {
    n = readInt(); m = readInt();
    map = utils.nextCharArray(n, m);
    vis=  new boolean[n + 1][m + 1];
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (!vis[i][j] && map[i][j] == '#') {
                cnt++;
                dfs(i, j);
            }
        }
    }
    printWriter.println(cnt);
}
// 偏移量,用于枚举8个方向
static int[] dx = new int[] {-1, -1, 0, 1, 1, 1, 0, -1}, dy = new int[] {0, 1, 1, 1, 0, -1, -1, -1};

public static void dfs(int a, int b) {
    for (int i = 0; i < 8; i++) {
        int nx = a + dx[i], ny = b + dy[i];
        if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny] && map[nx][ny] == '#') {
            vis[nx][ny] = true;
            dfs(nx, ny);
        }
    }
}

D - Printing Machine

题目描述
N N N 份产品在传送带上传送,传送带旁有一台打印机,第 i i i 份产品将在 T i T_i Ti 秒内进入打印机的打印范围内,并在 D i D_i Di 秒内离开打印机。现已知打印机一秒内最多只能打印一份产品,问打印机最多可以打印多少份产品。

思路:贪心+排序

  • 首先对产品进入打印机打印范围的时间升序排序,方便多个打印机同时入队。
  • 用一个优先队列(小顶堆)贪心地维护产品离开打印机的时间,让离开时间早的尽早打印。
public static void solve() throws IOException{
    int n = readInt();
    Pair[] pairs = new Pair[n + 1];
    for (int i = 1; i <= n; i++) {
        pairs[i] = new Pair(readLong(), readLong());
    }
    // 按进入打印机时间升序排序,方便入队
    Arrays.sort(pairs, 1, n + 1, (a, b) -> Long.compare(a.first, b.first));
    // 按离开打印机的时间升序排序
    PriorityQueue<Long> queue = new PriorityQueue<>();
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        queue.offer(pairs[i].first + pairs[i].second);
        // 进入打印机的时间相同,同时入队
        while (i + 1 <= n && pairs[i + 1].first == pairs[i].first) {
            queue.offer(pairs[i + 1].first + pairs[i + 1].second);
            i++;
        }
        long t = pairs[i].first;
        long bound = i + 1 <= n ? pairs[i + 1].first : Long.MAX_VALUE;
        // 在下一个产品来临之前打印
        while (queue.size() > 0 && t < bound) {
            long endTime = queue.poll();
            if (t <= endTime) {// 可以在对应时间离开打印机
                t++;
                cnt++;
            }
        }
    }
    printWriter.println(cnt);
}

E - Our clients, please wait a moment

题目描述
某国有 N N N 座城市,你要从 1 1 1号城市到达 N N N号城市。现在有两种交通工具可供选择:公司汽车和火车。从城市 i i i 到城市 j j j 所需的时间如下:

  • 乘公司汽车需 D i , j × A D_{i,j} \times A Di,j×A 分钟
  • 乘火车需 D i , j × B + C D_{i,j} \times B + C Di,j×B+C分钟

你可以从公司汽车换乘火车,但不能反之,而且你可以不花时间换乘。问从城市 1 1 1到城市 N N N最少需要多少分钟?

思路:分层图最短路+链式前向星存图

  • 构造三条边,① i → j i \to j ij,距离为 D i , j × A D_{i,j} \times A Di,j×A i → ( i + n ) i \to (i + n) i(i+n),距离为 0 0 0 ( i + n ) → ( j + n ) (i + n) \to (j + n) (i+n)(j+n),距离为 D i , j × B + C D_{i,j} \times B + C Di,j×B+C
    更复杂的分层图类似长下面这样,每两层之间至少有两个点相连
    在这里插入图片描述
static int[] head;
static long[] d;
static Edge[] edges;
static int n, a, b, c;
static boolean[] st;

public static void solve() throws IOException{
    n = readInt(); a = readInt(); b = readInt(); c = readInt();
    head = new int[n * 2 + 10];
    edges = new Edge[(2 * n) * (2 * n) + 10];
    Arrays.setAll(edges, edge -> new Edge());
    d = new long[n * 2 + 10];
    Arrays.fill(d, Long.MAX_VALUE);
    st = new boolean[n * 2 + 10];
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            int d = readInt();
            add(i, j, 1l * d * a);// 坐汽车
            add(i , i + n, 0l);// 两层之间建边,消费为0
            add(i + n, j + n, 1l * d * b + c);// 坐火车
        }
    }
    dijkstra();

    printWriter.println(Math.min(d[n], d[2 * n]));
}

public static void dijkstra() {
    PriorityQueue<long[]> queue = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1]));
    d[1] = 0;
    queue.offer(new long[] {1, 0});
    while (queue.size() > 0) {
        int t = (int) queue.poll()[0];
        if (st[t]) continue;
        st[t] = true;
        for (int i = head[t]; i != 0; i = edges[i].pe) {
            int to = edges[i].to;
            long w = edges[i].w;
            if (d[to] > d[t] + w) {
                d[to] = d[t] + w;
                queue.offer(new long[] {to, d[to]});
            }
        }
    }
}

public static void add(int a, int b, long c) {
    edges[idx] = new Edge(b, head[a], c);
    head[a] = idx++;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码,好长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长长
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值