解决问题:
双端队列主要解决图中边的权值只有0或者1的最短路问题
操作:
每次从队头取出元素,并进行拓展其他元素时
1、若拓展某一元素的边权是0,则将该元素插入到队头
2、若拓展某一元素的边权是1,则将该元素插入到队尾
注意:
按照正权图bfs的方向,如果这个点的状态已经被遍历到过,那么他一定是最短距离。
而对于含有0或负权的图来说则不然,需要自己本身这个点出队以后才能成为最优解。
借由Acwing 用户 小呆呆 的解释 如图:
思路:本题注意给定输入方式的图和方向转化,
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>
const int N = 1e6 + 10;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int r,c;
char s[510][510];
int sum;
int hr[4][2] = {{-1,-1},{-1,1},{1,1},{1,-1}};
int qwq[4][2] = {{-1,-1},{-1,0},{0,0},{0,-1}};
bool st[510][510];
int dist[510][510];
char stand[5] = "\\/\\/";// \转义,要俩
int bfs()
{
deque<PII>q;
memset(st,0,sizeof st);
memset(dist,INF,sizeof dist);
dist[0][0] = 0;
q.push_back({0,0});
while(q.size())
{
auto t = q.front();
q.pop_front();
int x = t.first;
int y = t.second;
if(x == r && y == c) return dist[r][c];
if(st[x][y]) continue;//dij
st[x][y] = 1;
for(int i = 0; i < 4; i ++)
{
int a = x + hr[i][0];
int b = y + hr[i][1];
if(a < 0 || a > r || b < 0 || b > c) continue;
int xx = x + qwq[i][0];
int yy = y + qwq[i][1];
int w = (s[xx][yy] != stand[i]);
int d = dist[x][y] + w;
if(d < dist[a][b])
{
dist[a][b] = d;
if(!w) q.push_front({a,b});
else q.push_back({a,b});
}
}
}
}
void solve()
{
sum = 0;
cin >> r >> c;
for(int i = 0; i < r; i ++) cin >> s[i];
if(r + c & 1) puts("NO SOLUTION");
else
{
sum = bfs();
cout << sum << endl;
}
}
int main()
{
int t;
cin >> t;
while(t --)
solve();
system("pause");
return 0;
}