冰块的滑行。
看到此题目求最短路径,想到了广搜算法,开一个结构体记录每一个球所在的位置和墙的状态。
采用广搜+Hash判重。试着写了一下。交上去,结果TLE了。本来也是看POJ上题目分类是深搜的,但给我直观印象求最短路还是采用BFS+Hash的方式。
晒一下我的代码和思路:模拟每一次移动,上下左右
#include<iostream>
#include<cstring>
using namespace std;
const int Arsize=5000;
const int HashTable=1123;
struct Node{
int x,y;
int Maps[22][22];
int dist;
};
Node location[Arsize];
int endx,endy,have_find,width,height;
int head[HashTable],Next[Arsize];
int Hash(int rear){
int i,j,v;
for(i=1,v=0;i<=width;i++){
for(j=1;j<=height;j++){
v=(v<<1)+location[rear].Maps[i][j];
}
}
return v%HashTable;
}
int try_to_insert(int rear){
int h=Hash(rear);
int u=head[h];
while(u){
if(memcmp(location[u].Maps,location[rear].Maps,sizeof(location[rear].Maps))==0&&location[u].x==location[rear].x&&location[u].y==location[rear].y)
return 0;
u=Next[u];
}
Next[rear]=head[h];
head[h]=rear;
return 1;
}
int bfs(void){
int front,rear,i,move,move_ok,nowx,nowy;
front=1;
rear=2;
while(front<rear){
Node & now=location[front];
if(location[front].dist>10){
return 0;
}
if(location[front].x==endx&&location[front].y==endy){
have_find=1;
return front;
}
for(i=1;i<=4;i++){
nowx=now.x;
nowy=now.y;
move_ok=0;
if(i==1){
if(now.Maps[nowx-1][nowy]==1)
continue;
for(move=nowx-1;move>0;move--){
if(now.Maps[move][nowy]==1||now.Maps[move][nowy]==3){
move_ok=1;
break;
}
}
if(move_ok){
memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
location[rear].Maps[move][nowy]=0;
location[rear].dist=now.dist+1;
location[rear].y=nowy;
if(now.Maps[move][nowy]==3)
location[rear].x=move;
else
location[rear].x=move+1;
if(try_to_insert(rear))
rear++;
}
}
else if(i==2){
if(now.Maps[nowx+1][nowy]==1)
continue;
for(move=nowx+1;move<=height;move++){
if(now.Maps[move][nowy]==1||now.Maps[move][nowy]==3){
move_ok=1;
break;
}
}
if(move_ok){
memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
location[rear].Maps[move][nowy]=0;
location[rear].dist=now.dist+1;
location[rear].y=nowy;
if(now.Maps[move][nowy]==3)
location[rear].x=move;
else
location[rear].x=move-1;
if(try_to_insert(rear))
rear++;
}
}
else if(i==3){
if(now.Maps[nowx][nowy-1]==1)
continue;
for(move=nowy-1;move>0;move--){
if(now.Maps[nowx][move]==1||now.Maps[nowx][move]==3){
move_ok=1;
break;
}
}
if(move_ok){
memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
location[rear].Maps[nowx][move]=0;
location[rear].dist=now.dist+1;
location[rear].x=nowx;
if(now.Maps[nowx][move]==3)
location[rear].y=move;
else
location[rear].y=move+1;
if(try_to_insert(rear))
rear++;
}
}
else{
if(now.Maps[nowx][nowy+1]==1)
continue;
for(move=nowy+1;move<=width;move++){
if(now.Maps[nowx][move]==1||now.Maps[nowx][move]==3){
move_ok=1;
break;
}
}
if(move_ok){
memcpy(location[rear].Maps,now.Maps,sizeof(now.Maps));
location[rear].Maps[nowx][move]=0;
location[rear].dist=now.dist+1;
location[rear].x=nowx;
if(now.Maps[nowx][move]==3)
location[rear].y=move;
else
location[rear].y=move-1;
if(try_to_insert(rear))
rear++;
}
}
}
front++;
}
return 0;
}
int main()
{
int i,j,front;
while(cin >> width >> height){
if(!height&&!width)
break;
memset(location,0,sizeof(location));
memset(head,0,sizeof(head));
have_find=0;
for(i=1;i<=height;i++){
for(j=1;j<=width;j++){
cin >> location[1].Maps[i][j];
if(location[1].Maps[i][j]==2){
location[1].x=i;
location[1].y=j;
}
if(location[1].Maps[i][j]==3){
endx=i;
endy=j;
}
}
}
location[1].dist=0;
front=bfs();
if(!have_find)
cout << "-1\n";
else{
cout << location[front].dist << endl;
}
}
return 0;
}
后面又google了一下解题报告,参考了下别人的代码,采用深搜的方式。操作数为深搜的层数,dfs形参中再带两个表示当前球位置的参数,一直搜下去就行了。
照这样写就AC了。
#include<iostream>
#include<cstring>
using namespace std;
int Maps[21][21];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int width,height,endx,endy,startx,starty,minstep;
void dfs(int steps,int nowx,int nowy){
int i,move_ok,move_x,move_y;
if(steps>10)
return ;
for(i=0;i<4;i++){
move_ok=0;
if(Maps[nowx+dx[i]][nowy+dy[i]]==1)
continue;
move_x=nowx;
move_y=nowy;
while(1){
move_x=move_x+dx[i];
move_y=move_y+dy[i];
if(move_x<=0||move_x>height||move_y<=0||move_y>width)
break;
if(Maps[move_x][move_y]==1){
move_ok=1;
break;
}
if(Maps[move_x][move_y]==3){
if(minstep>steps){
minstep=steps;
break;
}
}
}
if(move_ok){
Maps[move_x][move_y]=0;
dfs(steps+1,move_x-dx[i],move_y-dy[i]);
Maps[move_x][move_y]=1;
}
}
}
int main()
{
int i,j;
while(cin >> width >> height){
if(!width&&!height)
break;
memset(Maps,0,sizeof(Maps));
minstep=11;
for(i=1;i<=height;i++){
for(j=1;j<=width;j++){
cin >> Maps[i][j];
if(Maps[i][j]==2){
startx=i;
starty=j;
}
}
}
dfs(1,startx,starty);
if(minstep>10)
cout << "-1\n";
else
cout << minstep << endl;
}
return 0;
}