hdu 4856 tunnel(bfs+状态压缩dp)
2015-10-31 23:00
465 查看
先用bfs算出第i个通道的出口到第j个通道入口的最短路。然后用状态压缩dp求解。这里注意我们需要用到二维的dp数组,第二位储存在第i种状态下最后完成的状态。
状态压缩dp:用i表示状态,若第j种状态已完成,则:
dp[i][j]:做过i表示的通道,最后走的通道是j通道的最短距离。
想到状态压缩dp的话就很容易的出思路,我就总是错在一些小地方!!!
刚开始,我是准备用一个bfs计算出第i个通道出口到其他所有通道入口的距离。勉强写出来可是不能确定是否正确。对于通道入口与出口的记录也出现了混乱。直接导致我的dp特别难写。以后要注意一些小得细节。
状态压缩dp:用i表示状态,若第j种状态已完成,则:
dp[i][j]:做过i表示的通道,最后走的通道是j通道的最短距离。
dp[i][j]=min[dp[i][j],dp[i^(1<<k)][k]+dis[k][j]; 这里dis[k][j]表示通道k的出口到通道j的入口最短路距离
想到状态压缩dp的话就很容易的出思路,我就总是错在一些小地方!!!
刚开始,我是准备用一个bfs计算出第i个通道出口到其他所有通道入口的距离。勉强写出来可是不能确定是否正确。对于通道入口与出口的记录也出现了混乱。直接导致我的dp特别难写。以后要注意一些小得细节。
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> using namespace std; const int N=20; const int INF=1<<29; struct point{ int x,y; }start ,kk ; struct node { int x,y; int step; }; int dp[1<<15][20]; int dis ; int vis ; char map ; int n,m; int dir[4][2]={1,0,-1,0,0,1,0,-1}; int bfs(point s,point e) { memset(vis,0,sizeof(vis)); queue<node> q; node now,fi,hd; hd.x=s.x; hd.y=s.y; /*cout<<hd.x<<" "<<hd.y<<endl;*/ hd.step=0; q.push(hd); vis[hd.x][hd.y]=1; while(!q.empty()) { now=q.front(); q.pop(); /*cout<<"****************"<<endl;*/ if(now.x==e.x&&now.y==e.y) return now.step; for(int i=0;i<4;i++) { fi=now; fi.x+=dir[i][0]; fi.y+=dir[i][1]; fi.step++; int x=fi.x; int y=fi.y; if(x<0||y<0||x>n-1||y>n-1||vis[x][y]) continue; if(map[x][y]=='#') continue; q.push(fi); //cout<<x<<" "<<y<<endl; vis[x][y]=1; } } return INF; } int main() { /* freopen("in.txt","r",stdin);*/ while(cin>>n>>m) { for(int i=0;i<n;i++) { getchar(); scanf("%s",map[i]); } for(int i=0;i<m;i++) { scanf("%d%d%d%d",&start[i].x,&start[i].y,&kk[i].x,&kk[i].y); start[i].x--; start[i].y--; kk[i].x--; kk[i].y--; } for(int i=0;i<N;i++) for(int j=0;j<N;j++) dis[i][j]=INF; for(int i=0;i<m;i++) for(int j=0;j<m;j++) { if(i==j) { dis[i][j]=0; continue; } dis[i][j]=bfs(kk[i],start[j]); //cout<<i<<" "<<j<<endl; //cout<<dis[i][j]<<endl; } int big=1<<m; for(int i=0;i<big;i++) for(int j=0;j<m;j++) dp[i][j]=INF; for(int i=0;i<m;i++) dp[1<<i][i]=0; for(int i=0;i<big;i++) { for(int j=0;j<m;j++) { if(i&(1<<j)) { for(int k=0;k<m;k++) { if(dis[k][j]==INF || !(i&(1<<k)))continue ; dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+dis[k][j]); } } } } int minv=INF; for(int i=0;i<m;i++) minv=min(minv,dp[big-1][i]); if(minv==INF) cout<<-1<<endl; else cout<<minv<<endl; } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)
- Word Break I,II, Triangle,Palindrome Partitioning 动态规划 DP