http://acm.hdu.edu.cn/showproblem.php?pid=4856
题意:
一个
n
∗
n
n*n
n∗n的网格图中有
m
m
m个隧道,你可以从任意起点出发,问走过所有隧道需要的最小步数。
思路:
先
b
f
s
bfs
bfs预处理出任意两个点之间的最短路,然后状压dp
d
p
[
i
]
[
j
]
表
示
当
前
走
过
的
隧
道
状
态
为
i
,
最
后
走
到
的
隧
道
为
j
的
最
小
步
数
dp[i][j]表示当前走过的隧道状态为i,最后走到的隧道为j的最小步数
dp[i][j]表示当前走过的隧道状态为i,最后走到的隧道为j的最小步数
那么
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
d
p
[
i
(
1
<
<
j
)
]
[
k
]
+
d
i
s
(
k
,
j
)
)
dp[i][j] = min(dp[i][j], dp[i^(1<<j)][k]+dis(k,j))
dp[i][j]=min(dp[i][j],dp[i(1<<j)][k]+dis(k,j))
其中
d
i
s
(
j
,
k
)
dis(j,k)
dis(j,k) 表示隧道
j
j
j 的终点到隧道
k
k
k 的起点的最短路径长度。
#include<bits/stdc++.h>
using namespace std;
char mp[20][20];
int vis[20][20];
int n,m,num;
int dir[4][2] = {0,1,0,-1,1,0,-1,0};
int dis[20][20][20][20],dp[1<<17][20];
struct node{
int x,y,st,res;
};
struct state{
int x1,y1,x2,y2;
}p[20];
int ba;
int bfs(int s,int e){
queue<node>q;
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
node a,b;
a.x = s, a.y = e;
dis[s][e][s][e] = 0;
q.push(a);
while(!q.empty()){
b = q.front();
q.pop();
for(int i = 0; i < 4; i++){
a.x = b.x + dir[i][0];
a.y = b.y + dir[i][1];
if(a.x <= 0 || a.x > n || a.y <= 0 || a.y > n || vis[a.x][a.y] || mp[a.x][a.y] == '#') continue;
vis[a.x][a.y] = 1;
dis[s][e][a.x][a.y] = min(dis[s][e][a.x][a.y],dis[s][e][b.x][b.y] + 1);
q.push(a);
}
}
return 0;
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(dis,0x3f3f3f3f,sizeof(dis));
for(int i = 1; i <= n; i++){
scanf("%s",mp[i]+1);
}
int sz = 1<<m;
for(int i = 0; i < m; i++){
scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
}
int ans = 0x3f3f3f3f;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(mp[i][j] == '.'){
bfs(i,j);
}
}
}
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int j = 0; j < m; j++){
dp[1<<j][j] = 0;
}
for(int i = 0; i < sz; i++){
for(int j = 0; j < m; j++){
if(i&(1<<j)){
for(int k = 0; k < m; k++){
//if(j == k) continue;
if(i&(1<<k)){
dp[i][j] = min(dp[i][j], dp[i^(1<<j)][k] + dis[p[k].x2][p[k].y2][p[j].x1][p[j].y1]);
}
}
}
}
}
for(int i = 0; i < m; i++)
ans = min(ans, dp[sz-1][i]);
if(ans == 0x3f3f3f3f) ans = -1;
printf("%d\n",ans);
}
}