HDU_4856_Tunnels(BFS+状态压缩)
2014-07-15 09:15
316 查看
题型:搜索+DP
题意:
N*N的地图中,‘#’代表障碍物,‘.’代表可走。地图上有M条隧道的入口和出口,隧道是有向的。起始时可以选择地图上任意一个可走的点作为起点,在隧道中行走不算时间。问最少要多少时间可以把所有隧道走完。
分析:
在做西安邀请赛重现的时候,在这题上遇到的麻烦,主要还是怪自己太捉急,尝试了网络流和SPFA或者直接搜等各种无厘头的想法,但是都搞错的方向。
首先,在起点的选择上,一定是要选择某一条隧道的入口的,其实也是出口,因为过隧道不花时间。所以,花时间的地方就在地图上,即从某一个隧道的终点到另一个隧道的起点的距离,因此,要先BFS找出每一个隧道的终点到其他每一个隧道的起点的距离。
如何找出将所有隧道都走完的最短时间呢?
采用状态压缩,二进制枚举所有的隧道的使用情况,为了避免冲突,还要再加一维。表示当前状态的上一个状态的隧道。
设dp[i][j]表示从j隧道而来,且所走过的隧道为 i (i是二进制串)状态下的最短路程。
枚举1<<15中的所有状态,从当前状态推导出下一状态的所有情况并更新。
最终答案为min{dp[(1<<M)-1][i]}(i from 1 to m)。
代码:
题意:
N*N的地图中,‘#’代表障碍物,‘.’代表可走。地图上有M条隧道的入口和出口,隧道是有向的。起始时可以选择地图上任意一个可走的点作为起点,在隧道中行走不算时间。问最少要多少时间可以把所有隧道走完。
分析:
在做西安邀请赛重现的时候,在这题上遇到的麻烦,主要还是怪自己太捉急,尝试了网络流和SPFA或者直接搜等各种无厘头的想法,但是都搞错的方向。
首先,在起点的选择上,一定是要选择某一条隧道的入口的,其实也是出口,因为过隧道不花时间。所以,花时间的地方就在地图上,即从某一个隧道的终点到另一个隧道的起点的距离,因此,要先BFS找出每一个隧道的终点到其他每一个隧道的起点的距离。
如何找出将所有隧道都走完的最短时间呢?
采用状态压缩,二进制枚举所有的隧道的使用情况,为了避免冲突,还要再加一维。表示当前状态的上一个状态的隧道。
设dp[i][j]表示从j隧道而来,且所走过的隧道为 i (i是二进制串)状态下的最短路程。
枚举1<<15中的所有状态,从当前状态推导出下一状态的所有情况并更新。
最终答案为min{dp[(1<<M)-1][i]}(i from 1 to m)。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<queue> #define INF 0x3f3f3f3f #define mt(a,b) memset(a,b,sizeof(a)) using namespace std; int n,m; char Map[20][20]; bool vis[20][20]; int dist[20][20]; int dp[50000][20]; struct POINT { int x,y; } start[20],end[20]; struct Node { int x,y; int step; }; int dir1[] = {0,0,1,-1}; int dir2[] = {1,-1,0,0}; bool check(Node vw) { if(vw.x>=0&&vw.x<n && vw.y>=0&&vw.y<n && !vis[vw.x][vw.y] && Map[vw.x][vw.y]!='#') return true; else return false; } int BFS(POINT S,POINT E) { mt(vis,false); queue<Node> q; Node now; now.x = S.x; now.y = S.y; now.step = 0; q.push(now); vis[now.x][now.y] = true; while(!q.empty()) { now = q.front(); q.pop(); if(now.x==E.x && now.y==E.y) return now.step; for(int i=0; i<4; i++) { Node vw; vw.x = now.x + dir1[i]; vw.y = now.y + dir2[i]; vw.step = now.step +1 ; if(check(vw)) { q.push(vw); vis[vw.x][vw.y] = true; } } } return -1; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0; i<n; i++) { scanf("%s",Map[i]); } for(int i=0; i<m; i++) { scanf("%d%d%d%d",&start[i].x,&start[i].y,&end[i].x,&end[i].y); start[i].x--; start[i].y--; end[i].x--; end[i].y--; } mt(dist,0); for(int i=0; i<m; i++) { for(int j=0; j<m; j++) { if(i==j) { dist[i][j] = 0; continue; } dist[i][j] = BFS(end[i],start[j]); if(dist[i][j] == -1) dist[i][j] = INF; } } // for(int i=0;i<m;i++){ // for(int j=0;j<m;j++){ // printf("%5d ",dist[i][j]); // } // puts(""); // } mt(dp,INF); for(int i=0; i<m; i++) { dp[1<<i][i] = 0; } int big = (1<<m); for(int i=0; i<big; i++) { int tmp = i; for(int pos=0; pos<m; pos++) { if(!(tmp&1)) { for(int j=0; j<m; j++) { if((i>>j)&1) { dp[i|(1<<pos)][pos] = min(dp[i|(1<<pos)][pos],dp[i][j]+dist[j][pos]); } } } tmp >>= 1; } } int ans = INF; for(int i=0; i<m; i++) { ans = min(ans,dp[(1<<m)-1][i]); } if(ans == INF) ans = -1; printf("%d\n",ans); } return 0; }
相关文章推荐
- hdu 4856 Tunnels(bfs+状态压缩)
- hdu 4856 Tunnels(bfs+状态压缩)
- hdu 4856 Tunnels(bfs+状态压缩)
- HDOJ 题目4856 Tunnels(BFS+状态压缩,TSP)
- hdu 4856 Tunnels(动态规划&状态压缩)
- hdu 4856 Tunnels 状态压缩dp
- hdu 4856 tunnel(bfs+状态压缩dp)
- hdu~1429(bfs+状态压缩)
- HDU 4856 (状态压缩DP+TSP)
- BFS+状态压缩 hdu-1885-Key Task
- hdu 4771 Stealing Harry Potter's Precious (bfs+状态压缩)
- BFS+状态压缩 hdu-1885-Key Task
- hdu 5025 Saving Tang Monk (bfs+状态压缩)
- hdu 1429 (bfs+状态压缩)
- hdu 5094 Maze (bfs+状态压缩)
- hdu 1429 胜利大逃亡(续) bfs+状态压缩
- hdu 1429 胜利大逃亡(续) (bfs+状态压缩)
- poj1482 & hdu1818 It's not a Bug, It's a Feature!(bfs+状态压缩)
- hdu 1429 BFS+状态压缩
- hdu 2209 翻纸牌游戏(BFS+状态压缩)