Codeforces Round 929 (Div. 3)(F)

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;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值