题目链接:
游戏链接:
http://www.4399.com/flash/6860_3.htm
题意: 有一个长方体,给出它的起始位置(可能竖着,可能躺着)
问它通过滚动最少多少步能到达终点
解题思路:
BFS 由于每一步可能有竖着和横着两种情况,如果是躺着,不可能记录两个坐标,
我们只需要记录靠左上的节点即可,
然后再用一个state表示当前是竖着还是横着,一个dir表示正躺还是侧躺即可 第二个坐标可以根据这两个值得出来
还有要注意的是:1 破碎的块不能让长方体单独竖着
2 到达终点必须是竖着的
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define maxn 505
using namespace std;
struct node {
int x,y;
int state; // 0竖 1躺
int dir; // 1正躺 2侧躺
int step;
} head,t;
int vis[maxn][maxn][2][3];
char map[maxn][maxn];
int v[maxn][maxn];
int n,m,ex,ey;
int ok()
{
if(t.x<1||t.y<1||t.x>n||t.y>m||vis[t.x][t.y][t.state][t.dir])
return 0;
int xx=t.x,yy=t.y,dd=t.dir;
if(t.state==0) {
if(v[xx][yy]>=2)
return 1;
else
return 0;
} else {
int x1,y1;
if(dd==1)
x1=xx+1,y1=yy;
else
x1=xx,y1=yy+1;
if(map[xx][yy]=='#'||map[x1][y1]=='#')
return 0;
if(v[xx][yy]+v[x1][y1]>=2)
return 1;
else
return 0;
}
}
void bfs()
{
memset(vis,0,sizeof(vis));
queue<node>q;
vis[head.x][head.y][head.state][head.dir]=1;
q.push(head);
while(!q.empty()) {
head=q.front();
q.pop();
// cout<<head.x<<" "<<head.y<<" "<<head.state<<" "<<head.dir<<" "<<head.step<<endl;
if(head.state==0&&head.x==ex&&head.y==ey) {
printf("%d\n",head.step);
return;
}
if(head.state==0) {
t= {head.x-2,head.y,1,1,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x,head.y-2,1,2,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x,head.y+1,1,2,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x+1,head.y,1,1,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
} else if(head.state==1) {
if(head.dir==1) {
t= {head.x-1,head.y,0,0,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x+2,head.y,0,0,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x,head.y-1,1,1,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x,head.y+1,1,1,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
} else if(head.dir==2) {
t= {head.x,head.y-1,0,0,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x,head.y+2,0,0,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x-1,head.y,1,2,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
t= {head.x+1,head.y,1,2,head.step+1};
if(ok()) {
vis[t.x][t.y][t.state][t.dir]=1;
q.push(t);
}
}
}
}
printf("Impossible\n");
return;
}
char str[1000];
int main()
{
char a;
int ss;
int pos[3][2];
while(scanf("%d%d",&n,&m)&&(m+n)) {
ss=1;
for(int i=1; i<=n; i++){
scanf("%s",str+1);
for(int j=1; j<=m; j++) {
a=str[j];
map[i][j]=a;
if(a=='#')
v[i][j]=0;
else if(a=='E')
v[i][j]=1;
else if(a=='.')
v[i][j]=2;
else if(a=='O')
v[i][j]=2,ex=i,ey=j;
else if(a=='X') {
v[i][j]=2;
pos[ss][0]=i;
pos[ss++][1]=j;
}
}
}
head.state=0;
head.step=0;
head.x=pos[1][0];
head.y=pos[1][1];
if(ss==2)
head.dir=0;
else if(ss==3) {
head.state=1;
if(pos[2][0]-pos[1][0]==1)
head.dir=1;
else
head.dir=2;
}
bfs();
}
return 0;
}
代码写挫了,因为是在比赛中写出来的,当时还挺高兴的
首先 :躺着开始的两个坐标可以改进
bfs()重复12次同样的话(当时脑袋抽了 - -)
状态只需要三维即可 0竖着,1正躺,2侧躺即可
既然是比赛中写出来的 我也不想改了 保留原本吧