嗯……就是标准的状压dp,然而…………嗯…………spfa的时候稍微难一些……………………
重点是根本不知道取什么变量名2333333
相当于把每一个关键点的四个方向各设为一个点……以此来转移
grp[i][j]是(i,j)位置是否是墙
dis[i][j][k]是在(i,j)位置,面向k方向,从当前的spfa源点出发,最少多少次转弯可以到达
in_que就是是否在队列里
rec[i][di][j][dj]是从关键点i的di方向上的相邻点(当前状态是刚刚撞了i并停止),到关键点j的dj方向上的相邻点(同样也是刚撞了),需要的最小转弯次数(也就是spfa得到的距离)
f[s][i][di]中,s是状态(撞了哪些点),并且处在关键点i的di方向上的相邻点上
………………啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
反正代码不多也不难写………………………………………………………………………………………………然而…………………………嗯………………………………………………………………………………………………………………………………………………………………………………………………………………
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
变量名打错了调了一天…………………………我特么………………………………啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊垃圾游戏毁我青春耗我钱财颓我精神
u和v打反了……我……没看出来…………………………
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
不说了……上代码QAQ
#include<bits/stdc++.h>
#define MAXN 102
#define MAXT 15
#define INF 0x3f3f3f3f
using namespace std; int n,m,t;
const int cx[4]={0,1,0,-1};
const int cy[4]={1,0,-1,0};
int grp[MAXN][MAXN];
int Tx[MAXN],Ty[MAXN];
int sx,sy;
queue<int> que;
int dis[MAXN][MAXN][4];
int in_que[MAXN][MAXN][4];
void spfa(int x,int y,int dir){
memset(dis,INF,sizeof dis);
int tmp;
for(int i=0;i<4;++i)
dis[x][y][i]=(i!=dir), que.push(x),que.push(y),que.push(i), in_que[x][y][i]=1;
for(;que.size();){
x=que.front(),que.pop() , y=que.front(),que.pop() , dir=que.front(),que.pop();
in_que[x][y][dir]=0;
for(int i=0;i<4;++i){
int xx=x+cx[i],yy=y+cy[i];
if(grp[ xx ][ yy ])
for(int j=0;j<4;++j)
if(dis[ xx ][ yy ][j] > ( tmp = dis[x][y][dir] + (j!=i) + (i!=dir) ))
dis[ xx ][ yy ][j] = in_que[xx][yy][j] ?
tmp : ( que.push(xx) , que.push(yy) , que.push(j) ,
in_que[ xx ][ yy ][j]=1 , tmp );
}
}
}
int rec[MAXT][4][MAXT][4];
int f[1<<MAXT][MAXT][4];
char read_s[MAXN];
int main(){
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;++i){
scanf("%s",read_s+1);
for(int j=1;j<=m;++j) grp[i][j]=read_s[j]=='.';
}
for(int i=0;i<t;++i) scanf("%d%d",Tx+i,Ty+i);
memset(rec,INF,sizeof rec);
for(int u=0;u<t;++u)
for(int dir_u=0;dir_u<4;++dir_u){
int xu=Tx[u]+cx[dir_u],yu=Ty[u]+cy[dir_u];
if(grp[xu][yu]){
spfa(xu,yu,dir_u^2);
for(int v=0;v<t;++v)
for(int dir_v=0;dir_v<4;++dir_v){
int xx=Tx[v]+cx[dir_v],yy=Ty[v]+cy[dir_v];
if(grp[xx][yy])
rec[u][dir_u][v][dir_v]=dis[xx][yy][dir_v^2];
}
}
}
scanf("%d%d",&sx,&sy);
memset(f,INF,sizeof f);
for(int dir_s=0;dir_s<4;++dir_s){
spfa(sx,sy,dir_s);
for(int u=0;u<t;++u)
for(int dir_u=0;dir_u<4;++dir_u){
int xx=Tx[u]+cx[dir_u],yy=Ty[u]+cy[dir_u];
if(grp[xx][yy])
f[1<<u][u][dir_u]=min(f[1<<u][u][dir_u],dis[xx][yy][dir_u^2]+1);
}
}
for(int s=1;s<(1<<t);++s)
for(int u=0;u<t;++u)
if(s&(1<<u))
for(int v=0;v<t;++v)
if(!(s&(1<<v)))
for(int dir_u=0;dir_u<4;++dir_u)
for(int dir_v=0;dir_v<4;++dir_v)
f[s|(1<<v)][v][dir_v]=min(f[s|(1<<v)][v][dir_v], f[s][u][dir_u] + rec[u][dir_u][v][dir_v]);
int ans=INF;
for(int u=0;u<t;++u)
for(int dir=0;dir<4;++dir)
ans=min(ans,f[(1<<t)-1][u][dir]);
printf("%d",ans<=INF?ans:-1);
return 0;
}
/*
4 6 3
......
....#.
.....#
....#.
2 5
3 6
4 5
1 5
*/