180度转弯,这怕不是强互作用力赛车
Solution [HNOI2001]遥控赛车比赛
题目大意:给定一个(n)行(m)列的赛场,有些地方有障碍物,给定一个起点和终点,反应速度为(x in[1,10]),两次转弯(方向改变就算转弯,含180度)之间的时间间隔不能低于(x),求(xin [1,10])内的答案
最短路,bfs
分析:
我们尝试用多元组表示当前状态
为了知道我们在哪需要坐标((x,y))
为了知道我们还需要多久可以转弯需要冷却时间(cd)
为了知道我们的方向需要(d)
然后我们用((x,y,cd,d))就可以表示出当前的状态了
转移的话我们(d(u,d,cd))表示当前坐标为(u)(是个二元组),方向为(d),冷却时间为(cd)的最短距离,可以更新:
(d(v,d,cd-1))和(d(v,other ;d,x))((x)如上文)
用类似最短路的松弛,跑个(bfs)就好了
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 128;
int dis[4][12][maxn][maxn],inq[4][12][maxn][maxn],mp[maxn][maxn],deltax[] = {-1,0,1,0},deltay[] = {0,1,0,-1},begx,begy,endx,endy,n,m;
struct Node{
int d,cd,x,y;
};
inline int solve(int mxcd){
queue<Node> Q;
memset(dis,0x3f,sizeof(dis));
dis[0][mxcd][begx][begy] = 0,Q.push(Node{0,mxcd,begx,begy});
dis[1][mxcd][begx][begy] = 0,Q.push(Node{1,mxcd,begx,begy});
dis[2][mxcd][begx][begy] = 0,Q.push(Node{2,mxcd,begx,begy});
dis[3][mxcd][begx][begy] = 0,Q.push(Node{3,mxcd,begx,begy});
while(!Q.empty()){
Node now = Q.front();Q.pop();
inq[now.d][now.cd][now.x][now.y] = 0;
for(int i = 0;i < 4;i++){
int nx = now.x + deltax[i],ny = now.y + deltay[i];
if(nx < 1 || nx > n || ny < 1 || ny > m || !mp[nx][ny])continue;
if(i == now.d){
if(dis[now.d][now.cd][now.x][now.y] + 1 < dis[i][now.cd - 1 < 0 ? 0 : now.cd - 1][nx][ny]){
dis[i][now.cd - 1 < 0 ? 0 : now.cd - 1][nx][ny] = dis[now.d][now.cd][now.x][now.y] + 1;
if(!inq[i][now.cd - 1 < 0 ? 0 : now.cd - 1][nx][ny])Q.push(Node{i,now.cd - 1 < 0 ? 0 : now.cd - 1,nx,ny}),inq[i][now.cd - 1 < 0 ? 0 : now.cd - 1][nx][ny] = 1;
}
}else if(!now.cd){
if(dis[now.d][now.cd][now.x][now.y] + 1 < dis[i][mxcd - 1][nx][ny]){
dis[i][mxcd - 1][nx][ny] = dis[now.d][now.cd][now.x][now.y] + 1;
if(!inq[i][mxcd - 1][nx][ny])Q.push(Node{i,mxcd - 1,nx,ny}),inq[i][mxcd - 1][nx][ny] = 1;
}
}
}
}
int res = 0x3f3f3f3f;
for(int i = 0;i < 4;i++)
for(int j = 0;j <= mxcd + 1;j++)
res = min(res,dis[i][j][endx][endy]);
return res;
}
int main(){
// freopen("fafa.in","r",stdin);
scanf("%d %d",&n,&m);
scanf("%d %d %d %d",&begx,&begy,&endx,&endy);
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
scanf("%d",&mp[i][j]);
for(int i = 1;i <= 10;i++){
int ans = solve(i);
if(ans < 0x3f3f3f3f)printf("%d %d
",i,ans);
}
return 0;
}