题解:P13096 难以控制的滑板火箭
思路
大多数人一眼应该都能看出肯定最短路吧,这题连个顺序都没有,估计不会有人想去写那种基本没法做的动归。
显然的我们要求出从左上角到右下角的最短路,然后考虑怎么算。
除非巧合,否则不太可能最短路径正好落在区间内,所以我们对结果拓展一下,题目没有规定不能回到同一个点,那么我们就可以在两个相邻点上反复横跳。
但是反复横跳路径长度 \(L\gets L+2\),奇偶性不变,所以我们需要维护奇数路程和偶数路程两种最短路径,直接分层图最短路跑出来就行。
然后计算用时,对于 \(l<r\) 显然用时不会高于网格大小,所以直接暴力枚举时间,判断最大移动距离够不够抵达终点,是慢了点但是可靠够用,奇偶情况分开算,\(l\ne r\) 所以一定奇偶情况都有,可以忽略两者是不是都要算的问题。
对于 \(l=r\) 的情况需要单独考虑,毕竟只有一种情况。
- \(l=r\) 且为偶数时奇数抵达时间直接免谈,直接算偶数情况要多久,要特判偶数路径长不能抵达就输出 \(-1\)。
- \(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;
}

浙公网安备 33010602011771号