您的位置:首页 > 其它

HDOJ 1026 Ignatius and the Princess I 搜索最短路径

2013-05-26 14:29 183 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1026

最短很好解决,设置两个全局变量就可以搞定,每次到达出口时比较所用时间,但是记录最短路径比较复杂,目前还没有实现。题目中涉及到的边界剪枝,障碍剪枝

就不多说了,还是深度优先,先上代码,下次有时间再优化:

#include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <sstream>
#include <cstdlib>
#include <fstream>
#include <utility>
using namespace std;
char map[110][110];
vector<pair<int,int> > path;
void dfs(int sx,int sy,int endx,int endy);
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}};   //上下左右四个方向
int tsum,tmin;
int n,m,flag;
int main()
{

//ifstream fin;
//fin.open("abc.txt");
//cout<<fin.is_open()<<endl;
while(cin>>n>>m)
{
tsum=0;
flag=0;
tmin=999999;            //用来保存最短的时间,每次都要复制,不然多组测试数据
//时,始终保存的最短的一组测试结果
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>map[i][j];
dfs(0,0,n-1,m-1);
if(flag)
cout<<tmin<<endl;
else cout<<"God please help our poor hero."<<endl;
}
//fin.close();
return 0;

}
void dfs(int sx,int sy,int endx,int endy)
{

if(sx==endx&&sy==endy){
if(tsum<tmin)tmin=tsum;
flag=1;                 //标记是否能到达出口
return ;
}
for(int i=0;i<4;i++)
{
if(sx+dir[i][0]<0||sx+dir[i][0]>=n||sy+dir[i][1]<0||sy+dir[i][1]>=m)continue;
//以上是边界剪枝
if(map[sx+dir[i][0]][sy+dir[i][1]]=='.'){
tsum++;
map[sx+dir[i][0]][sy+dir[i][1]]='X';
dfs(sx+dir[i][0],sy+dir[i][1],endx,endy);
map[sx+dir[i][0]][sy+dir[i][1]]='.';
tsum--;
}
else if(map[sx+dir[i][0]][sy+dir[i][1]]>='1'&&map[sx+dir[i][0]][sy+dir[i][1]]<='9'){
tsum+=map[sx+dir[i][0]][sy+dir[i][1]]-'0';
tsum++;
int tmp=map[sx+dir[i][0]][sy+dir[i][1]]-'0';
map[sx+dir[i][0]][sy+dir[i][1]]='X';
dfs(sx+dir[i][0],sy+dir[i][1],endx,endy);
map[sx+dir[i][0]][sy+dir[i][1]]=tmp+'0';
tsum-=tmp;
tsum--;

}
}

}

今天在网上看了一个牛人写的完整算法,果然记录路径是最复杂的,而且才用了广度优先搜索,这里暂不说为什么不用深搜来记录路径,好吧先把代码贴上来学习下再说:

转自:http://www.wutianqi.com/?p=2354

#include <iostream>
#include <queue>
#include <stack>
using namespace std;

typedef struct Node{
int x, y, cost;      //cost即为到达每一步所用最短时间,注意是最短的
int prex, prey;      //prex,prey,回溯法时记录前一个位置的变量
}Node;

int N, M;
char maze[105][105];   // 记录初始输入
Node path[105][105];   // 记录路径
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// 判断(x, y)是否可行
bool isOK(int x, int y)
{
if(x>=0 && x<N && y>=0 && y<M && maze[x][y]!='X')
return 1;
else
return 0;
}

void Init()
{
int i, j;
for(i = 0; i < N; ++i)
for(j = 0; j < M; ++j)
path[i][j].cost = -1;
}

void backPath(int x, int y)    //用来输出路径
{
stack<Node> S;
Node a, b;
int cc = 1, tmp;

cout << "It takes " << path[N - 1][M - 1].cost
<< " seconds to reach the target position, let me show you the way." << endl;
a = path[N - 1][M - 1];
while(1)
{
if(a.x == 0 && a.y == 0)
break;
S.push(a);
a = path[a.prex][a.prey];
}                //使用栈来保存路径,从出口开始回溯

a = path[0][0];

while(!S.empty())
{
b = S.top();
S.pop();
if(maze[b.x][b.y] == '.')
cout << cc++ << "s:(" << a.x << "," << a.y << ")->(" << b.x << "," << b.y << ")" << endl;
else
{
cout << cc++ << "s:(" << a.x << "," << a.y << ")->(" << b.x << "," << b.y << ")" << endl;
tmp = maze[b.x][b.y] - '0';
while(tmp--)
cout << cc++ << "s:FIGHT AT (" << b.x << "," << b.y << ")" <<endl;
}
a = b;
}
cout<<"FINISH"<<endl;
}

int BFS(int x, int y)
{
queue<Node> Q;
Node a, b;
a.x = a.y = a.cost = a.prex = a.prey = 0;
if(maze[0][0] != '.')
a.cost = maze[0][0] - '0';
path[0][0] = a;
Q.push(a);

while(!Q.empty())
{
a = Q.front();
Q.pop();
for(int i=0; i<4; ++i) //广度优先搜索,对于每个点的上下左右四个位置上的点依次处理
{
b.x = a.x + dir[i][0];
b.y = a.y + dir[i][1];
if(!isOK(b.x, b.y))
continue;
if(maze[b.x][b.y] == '.')
b.cost = a.cost + 1;
else
b.cost = a.cost + maze[b.x][b.y]-'0' + 1;
if(b.cost < path[b.x][b.y].cost || path[b.x][b.y].cost == -1)
{                        //更新每个位置的最短时间
b.prex = a.x;
b.prey = a.y;
path[b.x][b.y] = b;
Q.push(b);
}
}
}
if(path[N - 1][M - 1].cost == -1)
{
cout << "God please help our poor hero." << endl;
cout << "FINISH" << endl;
return 0;
}
backPath(N-1, M-1);
}

int main()
{

while(cin >> N >> M)
{
memset(maze, 0, sizeof(maze));
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
cin >> maze[i][j];
Init();
BFS(0, 0);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: