poj 3009
题意:
搜索,已知起点和终点,求石子从起点到达终点的最短路,如果无法到达,则输出-1。石子移动的具体规则如下:
1、开始时,石子在起点s处
2、运动方向可以是水平或垂直的,不能斜方向运动
3、最开始的时候,你可以将石子向上下左右任意一个方向抛,如果与它相邻的点是障碍物的话除外
4、一旦石子开始运动,有三种可能:
a、遇到障碍物,石子会停在障碍物的前一格,障碍物会消失
b、如果出界,游戏失败
c、到达终点,游戏结束并成功
5、如果移动的次数超过10次,将认为游戏是失败的
#include <iostream> using namespace std; const int MAX = 30; int map[MAX][MAX]; int dir[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}}; int R, C; int ans; bool InMap(int r, int c) { return (r >= 1 && r <= R && c <= C && c >= 1); } void Dfs(int r, int c, int steps) { int nr, nc; if (steps > 10 || steps > ans) { return ; } for (int i=0; i<4; i++) { nr = r; nc = c; // 不用担心越界问题:因为(nr,nc)在图的范围之内,而图又是从1开始编号,所以。。。 if (map[nr+dir[i][0]][nc+dir[i][1]] != 1) { while (map[nr+dir[i][0]][nc+dir[i][1]] != 1) { // 下一步 nr += dir[i][0]; nc += dir[i][1]; // 越界 if (!InMap(nr, nc)) { break; } if (map[nr][nc] == 3) { // 到达终点 if (steps + 1 < ans) { ans = steps + 1; } return ; } } if (InMap(nr, nc)) { // 障碍 map[nr+dir[i][0]][nc+dir[i][1]] = 0; Dfs(nr, nc, steps + 1); map[nr+dir[i][0]][nc+dir[i][1]] = 1; } } } } int main() { int sr,sc; while (scanf("%d%d", &C, &R) && C && R) { memset(map, 0, sizeof(map)); for (int r=1; r<=R; r++) { for (int c=1; c<=C; c++) { cin >> map[r][c]; if (map[r][c] == 2) { sr = r; sc = c; } } } ans = 999999; Dfs(sr, sc, 0); (ans > 10) ? cout << "-1" << endl : cout << ans << endl; } return 0; }
/*DFS+Vector+剪枝*/ //TLE //万恶的POJ好像和STL不兼容,剪枝还是超时 //vector的优势无法发挥啊。。。 #include<iostream> #include<vector> using namespace std; const int inf=11; typedef class { public: int r,c; //冰壶当前位置 bool status; //status冰壶当前状态:运动true ,静止false }SE; SE s,e; //记录冰壶起止点 int w,h; //场地size int MinStep; //最短路 void DFS(vector<vector<int> >board,int i,int j,bool status,int direction,int step,bool flag) { //direction:冰壶当前运动方向 North:0 West:1 South:2 East:3 //flag:是否消除direction方向下一格位置的石头 if(step>10) //剪枝,超过10步的走法就不再考虑了 return; if(board[i][j]==3) //终点 { if(MinStep>step) MinStep=step; return; } if(flag) //消除石头 { switch(direction) { case 0: {board[i-1][j]=0; break;} //board用vector表示的目的就是为了在当前步删除某位置的石头时 case 1: {board[i][j-1]=0; break;} //前一步并不会删除该位置的石头 case 2: {board[i+1][j]=0; break;} case 3: {board[i][j+1]=0; break;} } } if(!status) //静止 { if(i-1>=1 && (board[i-1][j]==0 || board[i-1][j]==3)) //North DFS(board,i-1,j,true,0,step+1,false); if(j-1>=1 && (board[i][j-1]==0 || board[i][j-1]==3)) //West DFS(board,i,j-1,true,1,step+1,false); if(i+1<=h && (board[i+1][j]==0 || board[i+1][j]==3)) //South DFS(board,i+1,j,true,2,step+1,false); if(j+1<=w && (board[i][j+1]==0 || board[i][j+1]==3)) //East DFS(board,i,j-1,true,3,step+1,false); } else if(status) //运动 { switch(direction) { case 0: { if(i-1<1) //预判下一步是否越界 return; else { if(board[i-1][j]==0) //下一位置为0且不越界,继续运动 DFS(board,i-1,j,true,0,step,false); else if(board[i-1][j]==1) //下一位置为1且不越界,停止运动,并消除下一位置的石头 DFS(board,i,j,false,0,step,true); else if(board[i-1][j]==3) //下一位置为3且不越界,运动到位置3后停止运动,游戏结束 DFS(board,i-1,j,false,0,step,false); } break; } case 1: { if(j-1<1) //预判下一步是否越界 return; else { if(board[i][j-1]==0) //下一位置为0且不越界,继续运动 DFS(board,i,j-1,true,1,step,false); else if(board[i][j-1]==1) //下一位置为1且不越界,停止运动,并消除下一位置的石头 DFS(board,i,j,false,1,step,true); else if(board[i][j-1]==3) //下一位置为3且不越界,运动到位置3后停止运动,游戏结束 DFS(board,i,j-1,false,1,step,false); } break; } case 2: { if(i+1>h) //预判下一步是否越界 return; else { if(board[i+1][j]==0) //下一位置为0且不越界,继续运动 DFS(board,i+1,j,true,2,step,false); else if(board[i+1][j]==1) //下一位置为1且不越界,停止运动,并消除下一位置的石头 DFS(board,i,j,false,2,step,true); else if(board[i+1][j]==3) //下一位置为3且不越界,运动到位置3后停止运动,游戏结束 DFS(board,i+1,j,false,2,step,false); } break; } case 3: { if(j+1>w) //预判下一步是否越界 return; else { if(board[i][j+1]==0) //下一位置为0且不越界,继续运动 DFS(board,i,j+1,true,3,step,false); else if(board[i][j+1]==1) //下一位置为1且不越界,停止运动,并消除下一位置的石头 DFS(board,i,j,false,3,step,true); else if(board[i][j+1]==3) //下一位置为3且不越界,运动到位置3后停止运动,游戏结束 DFS(board,i,j+1,false,3,step,false); } break; } } } return; } int main(void) { while(cin>>w>>h) { if(!w && !h) break; /*Structure the Board*/ MinStep=inf; vector<vector<int> >board(h+1,vector<int>(w+1)); for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) { cin>>board[i][j]; if(board[i][j]==2) { s.r=i; s.c=j; s.status=false; board[i][j]=0; //记录起点位置后,把它作为0处理 } if(board[i][j]==3) //终点是特别位置,冰壶经过或到达该格都会停止 { e.r=i; e.c=j; } } /*Search the min path*/ DFS(board , s.r , s.c , s.status , 0 , 0 , false); if(MinStep<=10) cout<<MinStep<<endl; //DFS里面虽然剪枝了,但是可能把全部走法都剪了,因此还是要判断 else cout<<-1<<endl; /*Relax*/ // board.swap(vector<vector<int> >()); //POJ好像禁用swap() } return 0; }
作者:sam
出处:http://www.cnblogs.com/samjustin/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。