题意: 给了n*n 的地图,M条单向隧道,问最小时间访问所有隧道一遍;如果不可以输出-1;
先用dfs 找出 某一隧道的出口 到 其他隧道入口的 dis ; dfs 时,用vis[st.x][st.y][i][j] 去标记从 起点st 到(i,j) 的最小距离,当搜索是当前的dep >= vis,即可剪枝,不必再搜!
哈密顿用状态压缩DP :dp[x][i] : x 表访问的状态; i 表示此状态最后一个访问的节点号;
dp[0001][1] 表示当前只访问过1号,最后一次访问时1 ; 如果此时又1到2号的道路 ,那么状态即可转移为 dp[0011][2] = min(,dp[0001][1]+dist[1][2]);
状态转移方程为: dp[x][i] <--- dp[x-(1<<i)][j];
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<map>
#include<set>
using namespace std;
const int M=18;
char pos[M][M];
struct node{
int x,y;
};
struct P{
node st,ed;
void init(){
scanf("%d%d%d%d",&st.x,&st.y,&ed.x,&ed.y);
st.x--;st.y--;ed.x--;ed.y--;
}
}a[M];
int n,m;
int vis[M][M][M][M],dist[M][M];
int dp[1<<16][16];
node st;
bool check(int &x,int y){
if(x!=-1 && x<=y) return 1;
x=y; return 0;
}
void dfs(int x,int y,int dep){
if(x<0 || x>=n || y<0 || y>=n ||pos[x][y]=='#') return ;
if(check(vis[st.x][st.y][x][y],dep)) return ;
// printf("vis[%d][%d][%d][%d]= %d\n",st.x,st.y,x,y,vis[st.x][st.y][x][y]);
dfs(x+1,y,dep+1);
dfs(x-1,y,dep+1);
dfs(x,y+1,dep+1);
dfs(x,y-1,dep+1);
}
void deal_min(int &x,int y){
if(y==-1) return ;
else if(x==-1) x=y;
else x=min(x,y);
}
int main()
{
// freopen("in.in","r",stdin);
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<n;i++)
scanf("%s",pos[i]);
for(int i=0;i<m;i++)
a[i].init();
memset(vis,-1,sizeof(vis));
memset(dist,-1,sizeof(dist));
for(int i=0;i<m;i++){
st=a[i].ed;
dfs(st.x,st.y,0);
for(int j=0;j<m;j++)if(j!=i){
dist[i][j]=vis[st.x][st.y][a[j].st.x][a[j].st.y];
}
}
// for(int i=0;i<m;i++)
// for(int j=0;j<m;j++)
// printf("dist[%d][%d]= %d\n",i,j,dist[i][j]);
memset(dp,-1,sizeof(dp));
for(int i=0;i<m;i++) dp[1<<i][i]=0;
for(int x=1;x<(1<<m);x++){
for(int i=0;i<m;i++) if((x>>i)&1){
for(int j=0;j<m;j++) if(i!=j && ((x>>j)&1)){
if(dist[j][i]!=-1 && dp[x-(1<<i)][j]!=-1)
deal_min(dp[x][i], dp[x-(1<<i)][j]+dist[j][i]);
}
}
}
int ans=-1,x=(1<<m)-1;
for(int i=0;i<m;i++){
deal_min(ans,dp[x][i]);
}
printf("%d\n",ans);
}
return 0;
}