蓝桥杯:染色时间

蓝桥杯:染色时间https://www.lanqiao.cn/problems/2386/learning/?contest_id=80

问题描述

输入格式

输出格式

样例输入输出

样例输入

样例输出

评测用例规模与约定

解题思路:优先队列

AC代码(Java):


问题描述

        小蓝有一个 n 行 m 列的白色棋盘, 棋盘的每一个方格都可以被染成彩色。

        每个方格有一个染色时间{\color{Red} Tij}​, 不同方格的染色时间可能不同。如果一个方 格被触发了染色, 这个方格就会在 {\color{Red} Tij}秒之后变成彩色, 然后将自己上下左右四 个方向相邻的方格触发染色。每个方格只能被触发染色一次, 第一次触发之后 的触发为无效触发。

        给定每个方格的染色时间, 在时刻 0 触发第一行第一列的方格染色, 请问 多长时间后整个棋盘完成染色。

输入格式

        输入的第一行包含两个整数 n,m, 分别表示棋盘的行数和列数。

        接下来 n 行, 每行 m 个正整数, 相邻的整数之间用一个空格分隔, 表示每 个方格的染色时间。该部分的第 i 行第 j 个整数表示 {\color{Red} Tij}​, 即第 i 行第 j 列的方 格的染色时间。

输出格式

         输出一行包含一个整数, 表示整个棋盘完成染色的时间。

样例输入输出

样例输入


2 3

1 2 3

4 5 6

样例输出

12

评测用例规模与约定

对于 30% 的评测用例, 1≤n,m≤10 。

对于 60% 的评测用例, 1≤n,m≤50 。

对于所有评测用例, 1≤n,m≤500,1≤{\color{Red} Tij}​≤1000 。

解题思路:优先队列

        首先我们分析一下,题目要求我们从0,0处开始染色,也就是我们让0,0开始染色的时候,它的上下左右四个方向所有使用的时间为 自身染色时间+0,0处的染色时间,如:

将0,0处染色之后,图中染色时间分布情况:
0 3 3
4 5 6

        我们知道,0,1处染色时间3肯定是要比1,0处染色时间快的,所以当0,1处染色完成,应该是这样的:

将0,1处染色之后,图中染色时间分布情况:
0 0 6
4 8 6

        其实这里就可以看出来了,可以依次将染色的点存入队列之中,每次取出耗时最短的点,然后将其上下左右四个位置加上自身染色所需要的时间即可。

        所以这道题可以用优先队列来做,我们定义一个类(结构体)Node,该类存放有三个属性,分别是x(行),y(列),time(染色累计耗时)。

   static class Node{
        int x;
        int y;
        int time; //耗时
        public Node(int x,int y,int time){
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }

        这样我们就可以将0,0处节点的信息存放到优先队列中,每次我们取出耗时最短的一个节点,y也就是先完成染色的节点先出来,然后将其染色累计耗时,添加到上下左右四个还没有染色的节点中(如果染色了,我们就将对应位置的节点的值设置为0,方便判断)。

        依次再存入节点中,这样每次取出一个完成染色的节点,并且向四周开始没有染色的节点染色,这样优先队列中的最后一个节点就是我们完成染色所需要的时间。

AC代码(Java):

        因为使用Scanner只通过了80%,但是这道题的思路应该就是优先队列不会错,所以我将输入流换成了StreamTokenizer,提高读取性能,才全部通过。

        关于输入输出流性能,可以看:JAVA 输入输出优化

import java.io.*;
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {

    static class Node{
        int x;
        int y;
        int time; //耗时
        public Node(int x,int y,int time){
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }

    static int[][] dires = {{-1,0},{0,-1},{1,0},{0,1}}; //四个方向,上,右,下,左
    
    //优化输入流
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    public static  int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException{
        //在此输入您的代码...
        int n = nextInt();
        int m = nextInt();
        int[][] map = new int[n][m];
        for(int i = 0;i<n;i++){
            for(int j = 0;j<m;j++)
                map[i][j] = nextInt();
        }
        
        //首先队列,每次耗时最短的节点先出队,最后出队的就是耗时最久的
        PriorityQueue<Node> pq = new PriorityQueue<>((n1, n2)->(n1.time-n2.time)); //升序排序
        pq.add( new Node(0,0,map[0][0]) );
        //令该处为0,代表这个位置已经染色过了
        map[0][0] = 0;

        int ans = 0;
        while(!pq.isEmpty()){
            Node node = pq.poll();
            //将node节点上下左右的节点入队,并修改自己为 0,代表该节点已经染色
            for(int[] dire : dires){
                int x = node.x+dire[0];
                int y = node.y+dire[1];
                if(x>=0 && x<n && y>=0 && y<m && map[x][y]!=0){
                    pq.add(new Node(x,y,map[x][y]+node.time));
                     //令该处为0,代表这个位置已经染色过了
                    map[x][y] = 0;
                }
            }
            //该位置已经染色
            map[node.x][node.y] = 0;
            ans = node.time;
        }

        System.out.println(ans);
    }
}

        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值