您的位置:首页 > 其它

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[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp bfs