您的位置:首页 > 其它

UVA 1601 The Morning after Halloween (优化BFS)

2017-09-05 12:43 453 查看
思路就是抽出可以走的路来形成一张新的图,因为题目保证了所有空格连通,否则就超时。

还有这题一次可以移动所有字母,这在移动的时候,就类似于FILL那题的倒水,用n层循环来组合所有的可能。

其次,如果不用以上的办法,用双向BFS也可以(书上是这么讲的,但我不确定不经过建新图的优化,双向BFS是否会超时,我没有验证过),还有A*算法也可以(这玩意以前听说过,这次趁机学一波)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
int edge[200][5],start[3],target[3],deg[200];//edge用来记录一个位置的所有邻接点,deg表示这个点一共有几个邻接点
const int dx[]={-1,1,0,0,0};
const int dy[]={0,0,1,-1,0};
int dist[200][200][200];//记录步数
struct Node{
int a,b,c;
};
void bfs(){
queue<Node> q;
memset(dist,-1,sizeof(dist));
dist[start[0]][start[1]][start[2]]=0;//起点
Node node;
node.a=start[0];node.b=start[1];node.c=start[2];
q.push(node);
while(!q.empty()){
Node nd;
nd=q.front();
q.pop();
if(nd.a==target[0]&&nd.b==target[1]&&nd.c==target[2]) {printf("%d\n",dist[nd.a][nd.b][nd.c]);return;}
for(int i=0;i<deg[nd.a];i++){ //三重循环组合出每一步的所有可能
int na=edge[nd.a][i];
for(int j=0;j<deg[nd.b];j++){
int nb=edge[nd.b][j];
if(nb==na||(na==nd.b&&nb==nd.a))continue;//每下一层循环就判断与前面的点是否冲突
for(int k=0;k<deg[nd.c];k++){
int nc=edge[nd.c][k];
if(nc==na||(na==nd.c&&nc==nd.a))continue;
if(nb==nc||(nc==nd.b&&nb==nd.c))continue;
if(dist[na][nb][nc]!=-1)continue;
dist[na][nb][nc]=dist[nd.a][nd.b][nd.c]+1;//加一步
Node u;
u.a=na;u.b=nb;u.c=nc;
q.push(u);

}
}
}
}

}

int main()
{
int w,h,n;
while(scanf("%d%d%d",&w,&h,&n)==3&&n){
char mp[20][20];
memset(mp,0,sizeof(mp));
for(int i=0;i<=h;i++)
fgets(mp[i],20,stdin);//由于fgets会读入第一行三个数字之后的换行符,所以我这里行从1开始记录
/*for(int i=1;i<=h;i++){
for(int j=0;j<w;j++)
printf("%c",mp[i][j]);
printf("\n");
}*/

int id[200][200],cnt=0,tmpx[200],tmpy[200];
for(int i=1;i<=h;i++)
for(int j=0;j<w;j++){
if(mp[i][j]!='#'){
id[i][j]=cnt;//记录这个点是第几个
tmpx[cnt]=i;//记录各个位置的坐标
tmpy[cnt]=j;
if(islower(mp[i][j])) start[mp[i][j]-'a']=cnt;
if(isupper(mp[i][j])) target[mp[i][j]-'A']=cnt;
cnt++;
}
}
for(int i=0;i<cnt;i++){//逐个完整每个点的邻接表
deg[i]=0;
for(int k=0;k<5;k++){
int nx=tmpx[i]+dx[k],ny=tmpy[i]+dy[k];//上面记录的该点位置来走五个方向
if(mp[nx][ny]!='#')
edge[i][deg[i]++]=id[nx][ny];//记录第i个点所有相邻点,deg[i]++是每有一个邻接点,该点的邻接数就+1
}
}
if(n<=2){ //少于三个的时候,伪造一个独立的位置,放置第三个点
deg[cnt]=1;
edge[cnt][0]=cnt;
start[2]=target[2]=cnt;
cnt++;
}
if(n<=1){ //同上
deg[cnt]=1;
edge[cnt][0]=cnt;
start[1]=target[1]=cnt;
cnt++;
}
bfs();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: