F - Turtle Mission: Robot and the Earthquake
题意:题目很长,大致意思是一个有障碍物的迷宫,要求从起点走到终点,且单位时间障碍物会循环上移一格。你能够向右或者循环向下或者循环向上走。
分析:注意到终点那一列是必定没有障碍物的,因此考虑走到终点那一列即可。可以发现:由于障碍物会循环上移,因此对于自身而言,循环向上走等于没走(障碍物相对位置不变)。因此循环向上走只会在最后一列出现。接下来仅考虑向下走和向右走,就是一个普通的bfs了(注意判断一下障碍物)。最后再将最后一列到终点的时间加上去即可取最小值即可。
// Problem: F. Turtle Mission: Robot and the Earthquake
// Contest: Codeforces - Codeforces Round 929 (Div. 3)
// URL: https://codeforces.com/contest/1933/problem/F
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second
#define endl '\n'
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
return b > 0 ? gcd(b , a % b) : a;
}
LL lcm(LL a , LL b){
return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
for(int i = 0 ; i <= n ; i ++){
a[i] = 0;
}
}
struct Node{
int x , y , t;
};
void solve()
{
cin >> n >> m;
int mp[n][m];
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
cin >> mp[i][j];
}
}
Node dp[n][m];
int vis[n][m];
memset(vis , 0 , sizeof vis);
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
dp[i][j] = {i , j , inf};
}
}
dp[0][0] = {0 , 0 , 0};
queue<Node>q;
q.push(dp[0][0]);
while(!q.empty()){
auto tmp = q.front();
q.pop();
int ti = tmp.t;
int tx = tmp.x;
int ty = tmp.y;
if(vis[tx][ty])
continue;
dp[tx][ty].t = ti;
vis[tx][ty] = 1;
int nx2 = (tx + 1) % n;
int nx3 = tx;
int ny2 = ty;
int ny3 = ty + 1;
int nt = ti + 1;
//向下
int px = (tx + ti) % n;
if(mp[(px + 1) % n][ny2] == 0 && mp[(px + 2) % n][ny2] == 0){
q.push({nx2 , ny2 , nt});
}
//向右
if(ny3 < m && mp[(px + 1) % n][ny3] == 0){
q.push({nx3 , ny3 , nt});
}
}
int ans = inf;
for(int i = 0 ; i < n ; i ++){
ans = min(ans , dp[i][m - 1].t + min(i + 1 , n - 1 - i));
}
if(ans < inf)
cout << ans << endl;
else
cout << -1 << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(10);
int t=1;
cin>>t;
while(t--)
{
solve();
}
return 0;
}