题目链接
5 4 ....# ...#. ..... ..... ..... 2 3 1 4 1 2 3 5 2 3 3 1 5 4 2 1
7
题意:n*n的网格图,‘.’ 可以走,‘#’不可以走。有m条隧道,每条隧道有一个起点、终点。从一个点走到相邻的点要1分钟。求访问完所有隧道的最短时间,一条隧道只能访问一次。
题解:由于m很小,我们可以状压。直接在原图上跑状压复杂度太高。所以,可以先求出连在隧道上的点之间的距离,在这些点上跑状压就行了(注意一些小的优化)。代码如下:
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<vector> #include<math.h> #include<string> #include<set> #include<map> #define nn 610000 #define inff 0x3fffffff using namespace std; typedef __int64 LL; typedef unsigned __int64 ULL; int n,m; int dir[4][2]={1,0,-1,0,0,1,0,-1}; char tu[25][25]; struct node { int x,y; node(){}; node(int xx,int yy) { x=xx,y=yy; } }u[40]; struct bian { int en,len,next; int z; }E[40*40*2]; int p[40],num; void init() { memset(p,-1,sizeof(p)); num=0; } void add(int st,int en,int len,int ty) { E[num].en=en; E[num].len=len; E[num].next=p[st]; E[num].z=ty; p[st]=num++; } int dis[20][20]; queue<node>que; void bfs(int x,int y) { int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { dis[i][j]=inff; } } dis[x][y]=0; que.push(node(x,y)); node sta; int dx,dy; while(que.size()) { sta=que.front(); que.pop(); for(i=0;i<4;i++) { dx=sta.x+dir[i][0],dy=sta.y+dir[i][1]; if(dx>=0&&dx<n&&dy>=0&&dy<n&&tu[dx][dy]!='#') { if(dis[dx][dy]==inff) { dis[dx][dy]=dis[sta.x][sta.y]+1; que.push(node(dx,dy)); } } } } } struct so { int id,zt; so(){} so(int x,int y) { id=x,zt=y; } }; int dp[40][(1<<15)+10]; bool inque[40][(1<<15)+10]; queue<so>q; int ans; void solve() { ans=inff; int i,j; for(i=0;i<=2*m;i++) { for(j=0;j<(1<<m);j++) { dp[i][j]=inff; inque[i][j]=false; } } dp[0][0]=0; q.push(so(0,0)); so sta; int w,zt; while(q.size()) { sta=q.front(); q.pop(); //cout<<sta.id<<" "<<sta.zt<<" "<<dp[sta.id][sta.zt]<<endl; inque[sta.id][sta.zt]=false; if(sta.zt==(1<<m)-1) { ans=min(ans,dp[sta.id][sta.zt]); continue; } for(i=p[sta.id];i+1;i=E[i].next) { w=E[i].en; zt=sta.zt; if(E[i].z>=0) { if(((1<<E[i].z)&zt)==0) zt+=(1<<E[i].z); else continue; } if(dp[w][zt]>dp[sta.id][sta.zt]+E[i].len) { dp[w][zt]=dp[sta.id][sta.zt]+E[i].len; if(!inque[w][zt]) { inque[w][zt]=true; q.push(so(w,zt)); } } } } } int main() { int i,j; int xx,x,y,yy; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<n;i++) { scanf("%s",tu[i]); } int cnt=0; for(i=0;i<m;i++) { scanf("%d%d%d%d",&x,&y,&xx,&yy); x--,y--,xx--,yy--; u[++cnt].x=x; u[cnt].y=y; u[++cnt].x=xx; u[cnt].y=yy; } init(); for(i=1;i<=cnt;i++) { bfs(u[i].x,u[i].y); if(i%2) { add(0,i,0,-1); add(i,i+1,0,i/2); } else for(j=1;j<=cnt;j+=2) { if(i==j) continue; add(i,j,dis[u[j].x][u[j].y],-1); } } solve(); if(ans==inff) ans=-1; printf("%d\n",ans); } return 0; }
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<vector> #include<math.h> #include<string> #include<set> #include<map> #define nn 610000 #define inff 0x3fffffff using namespace std; int n,m; char tu[20][20]; struct node { int x,y; node(){} node(int xx,int yy) { x=xx,y=yy; } }u[20],v[20]; struct bian { int en,next,len; }E[20*20*2]; int p[20],num; void init() { memset(p,-1,sizeof(p)); num=0; } void add(int st,int en,int len) { E[num].en=en; E[num].len=len; E[num].next=p[st]; p[st]=num++; } queue<node>que; int dis[20][20]; int dir[4][2]={1,0,-1,0,0,1,0,-1}; void bfs(int x,int y) { int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) { dis[i][j]=inff; } } dis[x][y]=0; que.push(node(x,y)); node sta; int dx,dy; while(que.size()) { sta=que.front(); que.pop(); for(i=0;i<4;i++) { dx=sta.x+dir[i][0],dy=sta.y+dir[i][1]; if(dx>=0&&dx<n&&dy>=0&&dy<n&&tu[dx][dy]=='.') { if(dis[dx][dy]==inff) { dis[dx][dy]=dis[sta.x][sta.y]+1; que.push(node(dx,dy)); } } } } } int dp[20][(1<<15)+10]; void solve() { int i,j,k; for(i=0;i<=m;i++) { for(j=0;j<(1<<m);j++) { dp[i][j]=inff; } } dp[0][0]=0; int w,zt; for(j=0;j<(1<<m);j++) { for(i=0;i<=m;i++) { if(dp[i][j]<inff) { for(k=p[i];k+1;k=E[k].next) { w=E[k].en; zt=j; if(((1<<(w-1))&zt)==0) { zt+=1<<(w-1); if(dp[w][zt]>dp[i][j]+E[k].len) { dp[w][zt]=dp[i][j]+E[k].len; } } } } } } int ans=inff; for(i=0;i<=m;i++) { ans=min(ans,dp[i][(1<<m)-1]); } if(ans==inff) ans=-1; printf("%d\n",ans); } int main() { int i,j; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<n;i++) { scanf("%s",tu[i]); } for(i=1;i<=m;i++) { scanf("%d%d%d%d",&u[i].x,&u[i].y,&v[i].x,&v[i].y); u[i].x--,v[i].x--,u[i].y--,v[i].y--; } init(); for(i=1;i<=m;i++) { bfs(v[i].x,v[i].y); add(0,i,0); for(j=1;j<=m;j++) { if(i==j) continue; add(i,j,dis[u[j].x][u[j].y]); } } solve(); } return 0; }