题解:P13096 难以控制的滑板火箭

思路

大多数人一眼应该都能看出肯定最短路吧,这题连个顺序都没有,估计不会有人想去写那种基本没法做的动归。

显然的我们要求出从左上角到右下角的最短路,然后考虑怎么算。

除非巧合,否则不太可能最短路径正好落在区间内,所以我们对结果拓展一下,题目没有规定不能回到同一个点,那么我们就可以在两个相邻点上反复横跳。

但是反复横跳路径长度 \(L\gets L+2\),奇偶性不变,所以我们需要维护奇数路程和偶数路程两种最短路径,直接分层图最短路跑出来就行。

然后计算用时,对于 \(l<r\) 显然用时不会高于网格大小,所以直接暴力枚举时间,判断最大移动距离够不够抵达终点,是慢了点但是可靠够用,奇偶情况分开算,\(l\ne r\) 所以一定奇偶情况都有,可以忽略两者是不是都要算的问题。

对于 \(l=r\) 的情况需要单独考虑,毕竟只有一种情况。

  1. \(l=r\) 且为偶数时奇数抵达时间直接免谈,直接算偶数情况要多久,要特判偶数路径长不能抵达就输出 \(-1\)
  2. \(l=r\) 且为奇数时偶数情况一定耗费偶数时长,奇数情况一定耗费奇数时间,分开讨论。

做完了,还有多测一定要清空。

代码实现

码风经典友善,可读性不必担心,长度中等。

#include<bits/stdc++.h>
#define int long long
using namespace std;
char x[1005][1005];
int dis[1005][1005][3],n,m;
struct Ty{int a,b,val;}J[10]={{0,0,2},{-1,-1,1},{-1,0,1},{-1,1,1},{0,-1,1},{0,1,1},{1,-1,1},{1,0,1},{1,1,1}};
queue<Ty>q;
Ty add(Ty a,Ty b){
	a.a+=b.a;
	a.b+=b.b;
	a.val+=b.val;
	return a;
}
bool over(Ty a,Ty b){
	a.a+=b.a;
	a.b+=b.b;
	a.val+=b.val;
	if(x[a.a][a.b]=='0')return 0;
	if(a.a<0||a.a>n||a.b<0||a.b>m)return 0;
	if(a.val>=dis[a.a][a.b][a.val%2])return 0;
	return 1;
}
signed main(){
	int T;
	scanf("%lld",&T);
	while(T--){
		scanf("%lld%lld",&n,&m);
		int L,R;
		scanf("%lld%lld",&L,&R);
		for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)dis[i][j][0]=dis[i][j][1]=1e9;
		dis[1][1][0]=0;
		for(int i=1;i<=n;i++)scanf("%s",x[i]+1);
		while(!q.empty())q.pop();
		q.push({1,1,0});
		while(!q.empty()){
			Ty now=q.front(),nxt;
			q.pop();
			//if(dis[n][m][0]<1e9&&dis[n][m][1]<1e9)break; 加上应该也不会错
			for(int i=1;i<=8;i++)if(over(now,J[i])){
				q.push(nxt=add(now,J[i]));
				dis[nxt.a][nxt.b][nxt.val%2]=nxt.val;
			}
		}
		if(dis[n][m][0]>=1e9&&dis[n][m][1]>=1e9){
			printf("-1\n");
			continue;
		}
		if(L==R){
			if(L%2){
				int ans=(dis[n][m][0]/(L*2)+(dis[n][m][0]%(L*2)>0))*2;
				ans=min(ans,((dis[n][m][1]-L)/(L*2)+((dis[n][m][1]-L)%(L*2)>0))*2+1);
				printf("%lld\n",ans);
			}
			else {
				if(dis[n][m][0]<1e9)printf("%lld\n",dis[n][m][0]/L+(dis[n][m][0]%L>0));
				else printf("-1\n");
			}
			continue;
		}
		else{
			int maxx=0;
			for(int i=1;;i++){
				maxx+=R;
				if(maxx>=dis[n][m][maxx%2]||maxx-1>=dis[n][m][1-maxx%2]){
					printf("%lld\n",i);
					break;
				}
			}
		}
	}
	return 0;
}
posted @ 2025-08-19 21:05  Igunareo  阅读(65)  评论(0)    收藏  举报