您的位置:首页 > 其它

<OJ_Sicily>1135飞越原野

2016-05-27 19:34 288 查看
Description
勇敢的德鲁伊法里奥出色的完成了任务之后,正在迅速的向自己的基地撤退。但由于后面有着一大群追兵,所以法里奥要尽快地返回基地,否则就会被敌人捉住。
终于,法里奥来到了最后的一站:泰拉希尔原野,穿过这里就可以回到基地了。然而,敌人依然紧追不舍。不过,泰拉希尔的地理条件对法里奥十分有利,众多的湖泊随处分布。敌人需要绕道而行,但法里奥拥有变成鹰的特殊能力,使得他能轻轻松松的飞越湖面。当然,为了保证安全起见,法里奥还是决定找一条能最快回到基地的路。
假设泰拉希尔原野是一个m*n的矩阵,它有两种地形,P表示平地,L表示湖泊,法里奥只能停留在平地上。他目前的位置在左上角(1,1)处,而目的地为右下角的(m,n)。法里奥可以向前后左右四个方向移动或者飞行,每移动一格需要1单位时间。而飞行的时间主要花费在变形上,飞行本身时间消耗很短,所以无论一次飞行多远的距离,都只需要1单位时间。飞行的途中不能变向,并且一次飞行最终必须要降落在平地上。当然,由于受到能量的限制,法里奥不能无限制的飞行,他总共最多可以飞行的距离为D。在知道了以上的信息之后,请你帮助法里奥计算一下,他最快到达基地所需要的时间。
Input
第一行是3个正整数,m(1≤m≤100),n(1≤n≤100),D(1≤D≤100)。表示原野是m*n的矩阵,法里奥最多只能飞行距离为D。
接下来的m行每行有n个字符,相互之间没有空格。P表示当前位置是平地,L则表示湖泊。假定(1,1)和(m,n)一定是平地。
Output
一个整数,表示法里奥到达基地需要的最短时间。如果无法到达基地,则输出impossible。 
解题思路:使用广度搜索算法解决该问题。下面的算法参考了网上他人算法。首先创建一个结构体Node,用于存储状态,结构体Node的状态包括所在的位置x,y以及还能飞的距离p。从起点出发,将起点状态x=0,y=0,p=D压入deque。然后逐个取出deque中的首元素,对该元素进行四周搜索,寻找下一种合适的状态,将其压入deque中。使用3维矩阵来记录状态点是否出现过。
#include <iostream>
#include <stdio.h>
#include <deque>
#include <memory.h>
using namespace std;

struct Node{
int x, y; // 表示点的位置
int p; // 表示此时还能飞的距离
};
char graph[120][120];
bool visited[120][120][120];
int m, n, D;
int mov[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
deque<Node> q;

bool can_vis(int x, int y, int p){
if (x >= 0 && x < m && y >= 0 && y < n && graph[x][y] == 'P' && visited[x][y][p] == false) {
return true;
}
else return false;
}

int main() {
// insert code here...
int i,j,size;
Node tmp, tmp1;
int result, flag;
while (scanf("%d",&m)!=EOF) {
scanf("%d%d", &n,&D);
for(i = 0; i<m; i++){
scanf("%s",&graph[i]);
}
memset(visited, 0, sizeof(visited));

tmp.x = 0;
tmp.y = 0;
tmp.p = D;
result = 0;
flag = 0;
visited[tmp.x][tmp.y][tmp.p] = true;
q.clear();
q.push_back(tmp);
while (!q.empty()) {
size = q.size();
while (size --) {
tmp = q.front();
q.pop_front();
if (tmp.x == (m-1) && tmp.y == (n -1)) { // 已经到达终点,直接跳出
flag = 1;
break;
}
for (i = 0 ; i < 4; i++) { // 将周围合适的点存入
if (can_vis(tmp.x + mov[i][0], tmp.y + mov[i][1], tmp.p) == true) {
tmp1.x = tmp.x + mov[i][0];
tmp1.y = tmp.y + mov[i][1];
tmp1.p = tmp.p;
visited[tmp1.x][tmp1.y][tmp1.p] = true;
q.push_back(tmp1);
}
}
for (i = 0; i < 4; i++) { // 查找能飞的区域
for (j = 0; j <= tmp.p; j++) {
tmp1.x = tmp.x + mov[i][0] * j;
tmp1.y = tmp.y + mov[i][1] * j;
tmp1.p = tmp.p - j;
if (can_vis(tmp1.x, tmp1.y, tmp1.p) == true) {
visited[tmp1.x][tmp1.y][tmp1.p] = true;
q.push_back(tmp1);
}
}
}
}
if (flag == 1) break;
result ++;
}
if (flag == 1) cout << result << endl;
else cout << "impossible" << endl;

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sicily 算法