洛谷题解-[ABC079D] Wall (dijkstra / Floyd)
https://www.luogu.com.cn/problem/AT_abc079_d
题目描述
魔法少女のjoisinoお姉ちゃんは、この世にあるすべての数字を 1 1 1 に変えてやろうと思い立ちました。
1 1 1 つの数字を i i i から j(0≦i,j≦9) j(0≦i,j≦9) j(0≦i,j≦9) に書き変えるには魔力 ci,j c_{i,j} ci,j が必要です。
今、目の前にある壁は縦方向に H H H、横方向に W W W のマス目になっていて、1 1 1 つ以上のマス目に 0 0 0 以上 9 9 9 以下の整数が 1 1 1 つずつ書かれています。
上から i(1≦i≦H) i(1≦i≦H) i(1≦i≦H) 番目、左から j(1≦j≦W) j(1≦j≦W) j(1≦j≦W) 番目のマスの情報として Ai,j A_{i,j} Ai,j が与えられ、
- Ai,j≠−1 A_{i,j}≠-1 Ai,j=−1 の場合はマスに Ai,j A_{i,j} Ai,j が書かれている
- Ai,j=−1 A_{i,j}=-1 Ai,j=−1 の場合はマスに数字が書かれていない
ことを意味します。
この壁に書かれている数字を最終的に全て 1 1 1 に変えるのに必要な魔力の最小量を求めてください。
输入格式
入力は以下の形式で標準入力から与えられる。
H H H W W W c0,0 c_{0,0} c0,0 ... ... ... c0,9 c_{0,9} c0,9 : : : c9,0 c_{9,0} c9,0 ... ... ... c9,9 c_{9,9} c9,9 A1,1 A_{1,1} A1,1 ... ... ... A1,W A_{1,W} A1,W : : : AH,1 A_{H,1} AH,1 ... ... ... AH,W A_{H,W} AH,W
输出格式
壁に書かれている数字を最終的に全て 1 1 1 に変えるのに必要な魔力の最小量を出力せよ。
题意翻译
【题目大意】
你面前有一堵墙,墙上有数字,你需要将墙上的数字都变成 1
。
现在给出一个 W×HW\times HW×H 的矩阵 AAA 表示墙上数字的情况。
其中若 Ai,j=−1A_{i,j}=-1Ai,j=−1 ,则表示位置 (i,j)(i,j)(i,j) 上没有数字,否则 Ai,jA_{i,j}Ai,j 的值表示墙上 (i,j)(i,j)(i,j) 位置的数字。
当然,你还有一张 10×1010\times 1010×10 的表 CCC,其中 Ci,jC_{i,j}Ci,j 表示把数字 iii 转化成数字 jjj 所需要的花费。
求花费的最小值。
【输入格式】
先输入两个数字 HHH , WWW 。
接下来输入表 CCC。
最后输入矩阵 AAA。
【输出格式】
一行,代表答案。
【数据范围】
1≤H,W≤2001\le H,W\le2001≤H,W≤200
1≤Ci,j≤103(i≠j)1\le C_{i,j}\le 10^3 (i\neq j)1≤Ci,j≤103(i=j)
Ci,j=0(i=j)C_{i,j}=0(i=j)Ci,j=0(i=j)
−1≤Ai,j≤9-1\le A_{i,j}\le 9−1≤Ai,j≤9
所有数据保证在 int
范围以内。
输入输出样例
2 4 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 2 9 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 0 9 9 9 9 9 9 2 9 9 9 0 9 9 2 9 9 9 9 9 9 9 0 -1 -1 -1 -1 8 1 1 8
12
5 5 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 999 999 999 999 999 999 999 999 999 999 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0
3 5 0 4 3 6 2 7 2 5 3 3 4 0 5 3 7 5 3 7 2 7 5 7 0 7 2 9 3 2 9 1 3 6 2 0 2 4 6 4 2 3 3 5 7 4 0 6 9 7 6 7 9 8 5 2 2 0 4 7 6 5 5 4 6 3 2 3 0 5 4 3 3 6 2 3 4 2 4 0 8 9 4 6 5 4 3 5 3 2 0 8 2 1 3 4 5 7 8 6 4 0 3 5 2 6 1 2 5 3 2 1 6 9 2 5 6
47
说明/提示
制約
- 1≦H,W≦200 1≦H,W≦200 1≦H,W≦200
- 1≦ci,j≦103 (i≠j) 1≦c_{i,j}≦10^3\ (i≠j) 1≦ci,j≦103 (i=j)
- ci,j=0 (i=j) c_{i,j}=0\ (i=j) ci,j=0 (i=j)
- −1≦Ai,j≦9 -1≦A_{i,j}≦9 −1≦Ai,j≦9
- 入力は整数からなる
- 壁には一つ以上の整数が書かれている
Sample Explanation 1
8 8 8 を 1 1 1 に変えるとき、 8 8 8 を 4 4 4 に変え、その後 4 4 4 を 9 9 9 に、9 9 9 を 1 1 1 に変えると必要な魔力が最小となります。 壁には 8 8 8 が 2 2 2 つ書かれているので、必要な魔力の最小量は 6×2=12 6×2=12 6×2=12です。
Sample Explanation 2
壁に書かれている数字を全く変える必要がない場合に注意してください。
1.最短路有中间点,题目可以借助中间点的也可以联想到最短路
2.最短路的点编号不一定为1开始,此题是从0开始,一定要注意点数开始下标
乍一看又是跟最短路不相干的题,但是仔细想想就可以发现是最短路的题
从把一个数字变成另一个数字时,可以使用另外一个数字作为 “跳板”(中间点),不一定要直接转化,所以很容易就可以想到最短路径。
同时给出的C比较像邻接矩阵
化简一下就是求1,2,3...n到1号点的最短路,仍然可以反向边处理,然后1到1...n号点求最短路
但是注意,此题是数字,包含0,所以建图的点从0~9即可
(解题算法:这里我选dij,题解里都是Floyd的,可以去看看题解)
#include <bits/stdc++.h> using namespace std; const int N=205; struct node { int v, w; bool operator <(const node &A) const { return w>A.w; }; }; vector<node> a[N]; priority_queue<node> q; int n, m, w1, x, dis[N], vis[N], ans=0; void dij(int s) { memset(dis, 63, sizeof dis); memset(vis, 0, sizeof vis); dis[s]=0, q.push({s, 0}); while (!q.empty()) { int u=q.top().v; q.pop(); if (vis[u]) continue; vis[u]=1; for (int i=0; i<a[u].size(); i++) { int v=a[u][i].v, w=a[u][i].w; if (!vis[v] && dis[v]>dis[u]+w) { dis[v]=dis[u]+w; q.push({v, dis[v]}); } } } } int main() { scanf("%d%d", &n, &m); for (int i=0; i<10; i++) for (int j=0; j<10; j++) { scanf("%d", &w1); a[j].push_back({i, w1}); } dij(1); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) { scanf("%d", &x); if (x==-1 || x==1) continue; ans+=dis[x]; } printf("%d", ans); return 0; }