1.染色时间 - 蓝桥云课
问题描述
小蓝有一个 n 行 m 列的白色棋盘,棋盘的每一个方格都可以被染成彩色。
每个方格有一个染色时间 tij,不同方格的染色时间可能不同。如果一个方格被触发了染色,这个方格就会在 tij 秒之后变成彩色,然后将自己上下左右四个方向相邻的方格触发染色。每个方格只能被触发染色一次,第一次触发之后的触发为无效触发。
给定每个方格的染色时间,在时刻 0 触发第一行第一列的方格染色,请问多长时间后整个棋盘完成染色。
输入格式
输入的第一行包含两个整数 n,m,分别表示棋盘的行数和列数。
接下来 n 行,每行 m 个正整数,相邻的整数之间用一个空格分隔,表示每个方格的染色时间。该部分的第 i 行第 j 个整数表示 tij,即第 i 行第 j 列的方格的染色时间。
输出格式
输出一行包含一个整数,表示整个棋盘完成染色的时间。
样例输入
3
1 2 3
4 5 6
样例输出
12
评测用例规模与约定
- 对于 30 的评测用例,1≤n,m≤10。
- 对于 60 的评测用例,1≤n,m≤50。
- 对于所有评测用例,1≤n,m≤500,1≤tij≤1000。
运行限制
- 最大运行时间:1s
- 最大运行内存:256M
思路:
问题本质与图论建模
-
触发机制类比边权:
-
每个方格的染色时间
t_ij
可视为从该方格到其相邻方格的“边权”。 -
当一个方格完成染色(触发时间 +
t_ij
),它才能触发相邻方格。相邻方格的触发时间等于当前方格的完成时间。
-
-
最长时间的计算:
-
所有方格完成染色的时间是其触发时间与自身染色时间之和。
-
最终答案即为所有方格中完成时间的最大值。
-
-
Dijkstra算法的适用性:
-
每个方格的触发时间需要尽可能早,这与Dijkstra求最短路径的思想一致。
-
优先队列确保每次处理当前触发时间最小的方格,保证后续更新的正确性。
-
Dijkstra算法的应用步骤
-
初始化触发时间:
-
起点
(0,0)
的触发时间为0,其他方格初始化为无穷大(表示未被触发)。
-
-
优先队列处理:
-
每次取出队列中触发时间最小的方格,计算其完成时间。
-
更新相邻方格的触发时间:若通过当前路径更早触发,则更新并入队。
-
-
结果计算:
-
遍历所有方格,计算触发时间与染色时间之和的最大值。
-
为什么不是普通的bfs?假设路径A触发时间为5秒,路径B触发时间为3秒,但路径B的节点在队列中排在路径A之后。
BFS会先处理路径A的节点,错误地将相邻方格的触发时间设为5+t,而非更优的3+t。使用优先队列是为了保证触发时间的最优性。每个节点的触发时间可能通过多条路径到达,必须选择最小的值。优先队列通过贪心策略和动态更新,确保所有节点的触发时间被正确计算,从而准确得到整个棋盘完成染色的时间。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9;
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
struct Node{int time,x,y;
};
struct CompareNode
{bool operator()(const Node& a, const Node& b) {return a.time > b.time; }
};
int t[505][505], dis[505][505];
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {cin >> t[i][j];}}memset(dis, 0x3f, sizeof dis);dis[1][1] = 0;priority_queue<Node, vector<Node>,CompareNode> pq;pq.push({0, 1, 1}); while (!pq.empty()) {auto node = pq.top();pq.pop();int time = node.time;int x = node.x;int y = node.y;if (time > dis[x][y]) {continue;}// int current_end = time + t[x][y];for (int k = 0; k < 4; ++k) {int tx = x + dx[k];int ty = y + dy[k];if (tx >= 1 && tx <= n && ty >= 1 && ty <= m) {if (dis[tx][ty] > time + t[x][y]) {dis[tx][ty] = time + t[x][y];pq.push({time + t[x][y], tx, ty});}}}}int ans = 0;for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {ans = max(ans, dis[i][j] + t[i][j]);}}cout << ans << endl;return 0;
}