冰块的滑行。
看到此题目求最短路径,想到了广搜算法,开一个结构体记录每一个球所在的位置和墙的状态。
采用广搜+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; }
照这样写就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; }