本文最后更新于 2024年7月27日 下午
今日内容:
Floyd
题目
一个公司在全国有 n
个分部,它们之间有的有道路连接。一开始,所有分部通过这些道路两两之间互相可以到达。
公司意识到在分部之间旅行花费了太多时间,所以它们决定关闭一些分部(也可能不关闭任何分部 ),同时保证剩下的分部之间两两互相可以到达且最远距离不超过
maxDistance
。
两个分部之间的 距离 是通过道路长度之和的
最小值 。
给你整数 n
,maxDistance
和下标从
0 开始的二维整数数组 roads
,其中
roads[i] = [ui, vi, wi]
表示一条从 ui
到
vi
长度为 wi
的 无向
道路。
请你返回关闭分部的可行方案数目,满足每个方案里剩余分部之间的最远距离不超过
maxDistance
。
注意 ,关闭一个分部后,与之相连的所有道路不可通行。
注意 ,两个分部之间可能会有多条道路。
思路
枚举每种关闭方案,使用Floyd求最短路,然后判断是否合法。
详见代码注释
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Solution {public : int numberOfSets (int n, int maxDistance, vector<vector<int >>& roads) { vector<vector<int >> matrix (n, vector <int >(n, INT_MAX / 2 )); for (auto & road : roads) { int x = road[0 ], y = road[1 ], weight = road[2 ]; matrix[x][y] = min (matrix[x][y], weight); matrix[y][x] = min (matrix[y][x], weight); } vector<vector<int >> f (n); auto check = [&](int s) -> bool { for (int i = 0 ;i < n;i++) { if ((s >> i) & 1 ) { f[i] = matrix[i]; } } for (int k = 0 ;k < n;k++) { if (((s >> k) & 1 ) == 0 ) continue ; for (int i = 0 ;i < n;i++) { if (((s >> i) & 1 ) == 0 ) continue ; for (int j = 0 ;j < n;j++){ f[i][j] = min (f[i][j], f[i][k] + f[k][j]); } } } for (int i = 0 ;i < n;i++) { if (((s >> i) & 1 ) == 0 ) continue ; for (int j = 0 ;j < i;j++) { if ((s >> j) & 1 && f[i][j] > maxDistance) { return false ; } } } return true ; }; int ans = 0 ; for (int s = 0 ;s < (1 << n);s++) { ans += check (s); } return ans; } };
A-star
题目
在象棋中,马和象的移动规则分别是“马走日”和“象走田”。现给定骑士的起始坐标和目标坐标,要求根据骑士的移动规则,计算从起点到达目标点所需的最短步数。
棋盘大小 1000 x 1000(棋盘的 x 和 y 坐标均在 [1, 1000]
区间内,包含边界)
输入描述
第一行包含一个整数 n,表示测试用例的数量,1 <= n <= 100。
接下来的 n 行,每行包含四个整数 a1, a2, b1,
b2,分别表示骑士的起始位置 (a1, a2) 和目标位置 (b1, b2)。
输出描述
输出共 n
行,每行输出一个整数,表示骑士从起点到目标点的最短路径长度。
提示信息
骑士移动规则如图,红色是起始位置,黄色是骑士可以走的地方。
盗链随想录
思路
推荐看随想录的图: 代码随想录
| A-star
A*是启发式搜索,一开始知道要去的地方在哪里,所以根据终点位置,和具体的题目情景,选择合适的距离计算方式(曼哈顿、欧拉、切比雪夫、信息熵……),根据距离来选择下一步怎么走。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <iostream> #include <queue> #include <string.h> using namespace std;int moves[1001 ][1001 ];int dir[8 ][2 ]={-2 ,-1 ,-2 ,1 ,-1 ,2 ,1 ,2 ,2 ,1 ,2 ,-1 ,1 ,-2 ,-1 ,-2 };int b1, b2;struct Knight { int x,y; int g,h,f; bool operator < (const Knight & k) const { return k.f < f; } }; priority_queue<Knight> que;int Heuristic (const Knight& k) { return (k.x - b1) * (k.x - b1) + (k.y - b2) * (k.y - b2); }void astar (const Knight& k) { Knight cur, next; que.push (k); while (!que.empty ()) { cur=que.top (); que.pop (); if (cur.x == b1 && cur.y == b2) break ; for (int i = 0 ; i < 8 ; i++) { next.x = cur.x + dir[i][0 ]; next.y = cur.y + dir[i][1 ]; if (next.x < 1 || next.x > 1000 || next.y < 1 || next.y > 1000 ) continue ; if (!moves[next.x][next.y]) { moves[next.x][next.y] = moves[cur.x][cur.y] + 1 ; next.g = cur.g + 5 ; next.h = Heuristic (next); next.f = next.g + next.h; que.push (next); } } } }int main () { int n, a1, a2; cin >> n; while (n--) { cin >> a1 >> a2 >> b1 >> b2; memset (moves,0 ,sizeof (moves)); Knight start; start.x = a1; start.y = a2; start.g = 0 ; start.h = Heuristic (start); start.f = start.g + start.h; astar (start); while (!que.empty ()) que.pop (); cout << moves[b1][b2] << endl; } return 0 ; }