题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856
题目大意:有一个迷宫。迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时。出隧道就耗时,你的任务是访问完所有隧道且仅一次,求最短耗时。
解题思路:
暑假练习的时候。把英文读了N遍也没理解题意。
其实就是个最后不回到开头的TSP。
首先求BFS求两两隧道之间的最短路,注意BFS的起点是隧道i的终点,BFS的终点是隧道j的起点。
一定要特判一下两个隧道终点和起点是否一样,如果一样话dis=0, 我因为BFS没注意这个WA了10几次。
PS. 根据esxgx大神的说法,所有最短路算法(Dijkstra or Bellman-Ford)在每两个点距离为1的时候都会退化成普通的BFS,于是你在这里相当于手艹了个最短路。
然后就是对所有隧道进行TSP。
dp[i][j]表示状态i时,在j点的最少耗时,然后就是赤裸裸的TSP了。TSP的写法不唯一,我从别人那扒的这种TSP稍微快点。
#include "cstdio" #include "string" #include "iostream" #include "cstring" #include "queue" #include "vector" using namespace std; int n,m,vis[20][20],dis[20][20],dir[4][2]={-1,0,1,0,0,-1,0,1},ans,dp[1<<15][20]; char map[20][20]; const int inf=0x3f3f3f3f; struct status { int x,y,dep; status(int x,int y,int dep):x(x),y(y),dep(dep) {} }; struct tunnel { int sx,sy,ex,ey; }T[25]; int bfs(status a,status b) { if(a.x==b.x&&a.y==b.y) return 0; //关键一步,如果两个隧道恰好拼在一起,则dis=0 memset(vis,0,sizeof(vis)); int ans=inf; queue<status> Q; Q.push(a); vis[a.x][a.y]=true; while(!Q.empty()) { status t=Q.front();Q.pop(); for(int s=0;s<4;s++) { int X=t.x+dir[s][0],Y=t.y+dir[s][1]; if(X<1||X>n||Y<1||Y>n||vis[X][Y]||map[X][Y]!=‘.‘) continue; vis[X][Y]=true; if(X==b.x&&Y==b.y) {ans=min(ans,t.dep+1);return ans;} Q.push(status(X,Y,t.dep+1)); } } return ans; } int main() { ios::sync_with_stdio(false); string tt; while(cin>>n>>m) { memset(dis,0,sizeof(dis)); for(int i=1;i<=n;i++) { cin>>tt; for(int j=0;j<tt.size();j++) map[i][j+1]=tt[j]; } for(int i=1;i<=m;i++) cin>>T[i].sx>>T[i].sy>>T[i].ex>>T[i].ey; for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) { if(i==j) {dis[i][j]=0;} else dis[i][j]=bfs(status(T[i].ex,T[i].ey,0),status(T[j].sx,T[j].sy,0)); } int cnt=1<<m,res=inf; for(int i=0;i<cnt;i++) { for(int j=1;j<=m;j++) { int s=(1<<(j-1)); if((i&s)==0) continue; if(i==s) dp[i][j]=0; else dp[i][j]=inf; for(int k=1;k<=m;k++) { int t=(1<<(k-1)); if((i&t)==0||k==j||dis[k][j]==inf) continue; dp[i][j]=min(dp[i][j],dp[i^s][k]+dis[k][j]); } if(i==cnt-1) res=min(res,dp[i][j]); } } if(res==inf) printf("-1\n"); else printf("%d\n",res); } }
11887989 | 2014-10-16 20:17:15 | Accepted | 4856 | 171MS | 2852K | 2290 B | C++ | Physcal |
时间: 2024-12-10 18:46:52