题目链接
一.题目内容
给一个n*m的矩阵,每一格要么是 * 代表障碍 ,要么是可走的1-100的整数。
① 只能上下左右走,输出从{r1,c1}到{r2,c2}最短路径,路径长度就是所走格子的和。
② 若每一步不能与前一步的方向相同,也就是只能转弯或者后退,输出从这时从{r1,c1}到{r2,c2}最短路径。
若无路径则输出 -1
样例解释
样例一:① 正常路线 10->3->6->14->8,值为41 。② 转弯路线 10->3->6->2->6->14->8,值为49。
二.解题思路
第一问直接dijkstra即可。
第二问也是dijkstra,但需要稍微变形。由于连续两步方向不能相同,则可以记录以下从不同方向走到某格的最短路,方向相同就不能走,若方向不同则更新对应方向的最短路,最后的结果从所有到达终点的最短路中比较得出。
三.解题代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define rrep(i, l, r) for (int i = l; i >= r; --i)
#define int long long
int dir[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; //四个方向的数组
const int N = 1e3 + 10, M = 1e9 + 7;
//-----------//
int n, m, r1, c1, r2, c2;
int a[N][N], dis[N][N],dis2[N][N][4];//四个方向的dis
bool vis[N][N];
bool check(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= m && a[x][y];
}
struct node {
int x, y, w, di;
friend bool operator<(const node &t1, const node &t2) {
return t1.w > t2.w;
}
};
int dj1() { //正常dijkstra
rep(i, 1, n) rep(j, 1, m) dis[i][j] = LLONG_MAX, vis[i][j] = 0;
priority_queue<node> q;
q.push(node{r1, c1, a[r1][c1], -1});
dis[r1][c1]=0;
while (q.size()) {
node cur = q.top();
q.pop();
if (vis[cur.x][cur.y]) continue;
if (cur.x == r2 && cur.y == c2) return dis[r2][c2];
vis[cur.x][cur.y] = 1;
rep(i, 0, 3) {
int x = cur.x + dir[i][0];
int y = cur.y + dir[i][1];
if (check(x, y) && !vis[x][y]) {
int d = cur.w + a[x][y];
if (dis[x][y] > d) {
dis[x][y] = d;
q.push(node{x, y, d, i});
}
}
}
}
return -1;
}
int dj2() { //修改版dijkstra
rep(i, 1, n) rep(j, 1, m) rep(k,0,3) dis2[i][j][k] = LLONG_MAX;
priority_queue<node> q;
q.push(node{r1, c1, a[r1][c1], -1});
rep(i,0,3) dis2[r1][c1][i]=0;
int ans=LLONG_MAX;
while (q.size()) {
node cur = q.top();
q.pop();
if (cur.x == r2 && cur.y == c2) ans=min(ans,cur.w);
//若到达终点更新答案
rep(i, 0, 3) {
int x = cur.x + dir[i][0];
int y = cur.y + dir[i][1];
if (check(x, y) && i!=cur.di) { //若方向不同则判断
int d = cur.w + a[x][y];
if (dis2[x][y][i] > d) {
dis2[x][y][i] = d;
q.push(node{x, y, d, i});
}
}
}
}
return ans==LLONG_MAX?-1:ans;
}
signed main() {
int cnt = 0;
while (cin >> n >> m >> r1 >> c1 >> r2 >> c2) {
rep(i, 1, n) {
rep(j, 1, m) {
string s;
cin >> s;
if (s == "*") a[i][j] = 0; //障碍设为0
else a[i][j] = stoll(s); //可走的格子为数字
}
}
cout << "Case " << ++cnt << ": " << dj1() << " "<< dj2() << endl;
}
}
四.小结
算是板子题,开始想的贪心,后来还是得弄四个方向的最短路才行。

这篇博客详细介绍了2015年湖南省第十一届大学生程序设计大赛E题的解题过程,主要涉及图论中的最短路径问题。作者使用Dijkstra算法分别解决两种路径约束条件下的最短路径问题,一种是允许直行,另一种必须转弯。在第二种情况下,需要记录不同方向到达某点的最短路径。博客提供了解题思路和C++代码实现。

&spm=1001.2101.3001.5002&articleId=127233938&d=1&t=3&u=fc602fbb25944805bfee0a9abd2ab5f2)
1424

被折叠的 条评论
为什么被折叠?



