Bob is travelling in Xi’an. He finds many secret tunnels beneath the city. In his eyes, the city is a grid. He can’t enter a grid with a barrier. In one minute, he can move into an adjacent grid with no barrier. Bob is full of curiosity and he wants to visit all of the secret tunnels beneath the city. To travel in a tunnel, he has to walk to the entrance of the tunnel and go out from the exit after a fabulous visit. He can choose where he starts and he will travel each of the tunnels once and only once. Now he wants to know, how long it will take him to visit all the tunnels (excluding the time when he is in the tunnels).
Input
The input contains mutiple testcases. Please process till EOF.
For each testcase, the first line contains two integers N (1 ≤ N ≤ 15), the side length of the square map and M (1 ≤ M ≤ 15), the number of tunnels.
The map of the city is given in the next N lines. Each line contains exactly N characters. Barrier is represented by “#” and empty grid is represented by “.”.
Then M lines follow. Each line consists of four integers x1, y1, x2, y2, indicating there is a tunnel with entrence in (x1, y1) and exit in (x2, y2). It’s guaranteed that (x1, y 1) and (x2, y2) in the map are both empty grid.
Output
For each case, output a integer indicating the minimal time Bob will use in total to walk between tunnels.
If it is impossible for Bob to visit all the tunnels, output -1.
Sample Input
5 4
....#
...#.
.....
.....
.....
2 3 1 4
1 2 3 5
2 3 3 1
5 4 2 1
Sample Output
7
因为数组开小了,错了不知道多少次,心态爆炸,最关键的是自己一直没有意识到这个问题
状态压缩DP,将集合中某个元素是否存在用二进制表示,如1001,表示元素1和元素4在集合中,而元素2,3不在。
状态的转移采用位运算的方法,确定i不在这个集合中,加入元素i,转移到新的状态,也就是变成了一个新的集合。
因为从1开始遍历,以1111为例。 这四个元素都在的集合,其二进制表示为1111,而能转移到1111状态的集合,他们的二进制表示都比1111小,所以一定会先遍历所有可到达的状态,进而能确保1111状态中记录的是最优情况。
可以把表示某一状态的数n,事先预处理n中已经有哪些元素加入,存入数组,就不用DP时每一位都算一遍了。
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 10000
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
struct Cord{
int x,y;
};
struct Tunnel{
Cord star,finish;
};
struct Recd{
int x,y;
int len;
};
int N,M;
int shif[5][2]={{0,1},{0,-1},{1,0},{-1,0}};
char store[18][18];
bool vis[20][20];
int dp[40000][15];
int dis[20][20];
vector<int> V[40000];
Tunnel tunnel[20];
int cal(Tunnel &a,Tunnel &b);
inline bool check(Cord &pos);
int main()
{
rep(i,1,1<<15){
rep(j,0,15){
if(i & (1<<j))
V[i].Push(j);
}
}
while(scanf("%d %d",&N,&M)!=EOF){
rep(i,1,N+1)
scanf("%s",store[i]+1);
rep(i,0,M){
scanf("%d %d %d %d",&tunnel[i].star.x,&tunnel[i].star.y,&tunnel[i].finish.x,&tunnel[i].finish.y);
}
//cal dis
rep(i,0,M){
rep(j,0,M){
if(i==j){
dis[i][j]=0;
continue;
}
dis[i][j]=cal(tunnel[i],tunnel[j]);
}
}
rep(i,1,1<<M){
rep(j,0,M)
dp[i][j]=INF;
}
rep(i,0,M){
dp[1<<i][i]=0;
}
rep(i,1,1<<M){
rep(x,0,getLen(V,i)){
int j=V[i][x];
int pre=i-(1<<j);
rep(k,0,M){
if(pre & (1<<k))
dp[i][j]=min(dp[i][j],dp[pre][k]+dis[k][j]);
}
}
}
int ans=INF;
rep(i,0,M){
ans=min(ans,dp[(1<<M)-1][i]);
}
if(ans>=INF)
ans=-1;
printf("%d\n",ans);
}
return 0;
}
int cal(Tunnel &a,Tunnel &b){
queue<Recd> Q;
memset(vis,0,sizeof(vis));
Q.push({a.finish.x,a.finish.y,0});
vis[a.finish.x][a.finish.y]=true;
while(!Q.empty()){
Recd now=Q.front();
Q.pop();
if(now.x==b.star.x && now.y==b.star.y){
return now.len;
}
Cord next;
rep(i,0,4){
next.x=now.x+shif[i][0],next.y=now.y+shif[i][1];
if(!check(next) || vis[next.x][next.y] || store[next.x][next.y]=='#')
continue;
vis[next.x][next.y]=true;
Q.push({next.x,next.y,now.len+1});
}
}
return INF;
}
inline bool check(Cord &pos){
if(pos.x>N || pos.x<=0 || pos.y>N || pos.y<=0){
return false;
}else
return true;
}