sicily 1135 飞越原野

题目思路:由于飞行的时候只计算变身的时间而不算飞行的时间,也就是说,走一步和飞一次(无论飞多久)花费的时间是一样的,因此,我们可以用广搜来解决这个问题。无论是飞行还是步行,都可以作为一个节点放到bfs状态的队列之中。


状态我用了一个结构体,内有主角的坐标位置、当前花销时间、可飞行的距离。既然是遍历,就要记着已经遍历过的位置,这里的visited数组有点特别,是一个三位数组,第一、二维分别表示坐标位置,第三维表示当前剩余能够飞行的距离。一开始我的visited数组只有两维,而在考虑飞行和步行的优先关系时,认为如果在同一时间,用飞的和用步行的都能到达某一个位置,那么步行肯定是比飞行优越的,所以在飞行到某个位置的时候,我就没有将visited数组相应的位置置为true,这就一直wa了。后来我重新考虑了飞行和步行的关系,认为,上述的情况下,的确步行是优越于飞行的,但是我没有考虑飞行和飞行之间的关系。如果首先可以飞行到位置A,飞行的距离比较长,将主角的能量都用完了。但如果主角可以从B点飞行较短的距离,也可以到达A点,但visited已经置为true了,就不能飞过去了,但如果能飞过去,而且下一步能够很快地飞到终点,那么算出来的结果一定是错的。


先上带有bug的代码。

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

struct Node{
    Node(int a, int b, int l, int t){
        x = a;
        y = b;
        left = l;
        time = t;
    }
    int x;
    int y;
    int left;
    int time;
};

int dir[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int m, n, d;
bool visited[101][101];
char matrix[101][101];

bool isValid(int x, int y){
    return x >= 1 && x <= m && y >= 1 && y <= n;
}

int main(){
    cin >> m >> n >> d;
    for(int i = 1; i <= m; ++i){
        for(int j = 1; j <= n; ++j){
            cin >> matrix[i][j];
        }
    }
/*  for(int i = 1; i <= m; ++i){
        for(int j = 1; j <= n; ++j){
            cout << matrix[i][j];
        }
        cout << endl;
    }
*/
    int result = 0;
    queue<Node> q;
    q.push(Node(1, 1, d, 0));
    memset(visited,false, sizeof(visited));
    visited[1][1] = true;
    while(!q.empty()){
        Node cur = q.front();
        q.pop();
        int tempx, tempy;
        for(int i = 0; i < 4; ++i){
            tempx = cur.x + dir[i][0];
            tempy = cur.y + dir[i][1];  
            if(isValid(tempx, tempy)){
                if(!visited[tempx][tempy] && matrix[tempx][tempy] == 'P'){
                    if(tempx == m && tempy == n){
                        result = cur.time + 1;
                        break;
                    }
                    q.push(Node(tempx, tempy, cur.left, cur.time+1));
                    visited[tempx][tempy] = true;
                }
            }
            else
                continue;
            for(int j = 2; j <= cur.left; ++j){
                tempx = cur.x + j*dir[i][0];
                tempy = cur.y + j*dir[i][1];
                if(isValid(tempx, tempy) && !visited[tempx][tempy] && matrix[tempx][tempy] == 'P'){
                    if(tempx == m && tempy == n){
                        result = cur.time + 1;
                        break;
                    }
                    q.push(Node(tempx, tempy, cur.left-j, cur.time+1));
                }
            }
            if(result != 0)
                break;
        }
        if(result != 0)
            break;
    }
    if(result != 0)
        cout << result << endl;
    else
        cout << "impossible" << endl; 
}                                 

再上正确的代码:

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

struct Node{
    Node(int a, int b, int l, int t){
        x = a;
        y = b;
        left = l;
        time = t;
    }
    int x;
    int y;
    int left;
    int time;
};

int dir[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int m, n, d;
bool visited[101][101][101];
char matrix[101][101];

bool isValid(int x, int y){
    return x >= 1 && x <= m && y >= 1 && y <= n;
}

int main(){
    cin >> m >> n >> d;
    for(int i = 1; i <= m; ++i){
        for(int j = 1; j <= n; ++j){
            cin >> matrix[i][j];
        }
    }
/*  for(int i = 1; i <= m; ++i){
        for(int j = 1; j <= n; ++j){
            cout << matrix[i][j];
        }
        cout << endl;
    }
*/
    int flag = false;
    queue<Node> q;
    q.push(Node(1, 1, d, 0));
    memset(visited,false, sizeof(visited));
    visited[1][1][d] = true;
    while(!q.empty()){
        Node cur = q.front();
        if(cur.x == m && cur.y == n){
            cout << cur.time << endl;
            flag = true;
            break;
        }
        q.pop();
        int tempx, tempy;
        for(int i = 0; i < 4; ++i){
            tempx = cur.x + dir[i][0];
            tempy = cur.y + dir[i][1];  
            if(isValid(tempx, tempy)){
                if(!visited[tempx][tempy][cur.left] && matrix[tempx][tempy] == 'P'){
                    q.push(Node(tempx, tempy, cur.left, cur.time+1));
                    visited[tempx][tempy][cur.left] = true;
                }
            }
            else
                continue;
            for(int j = 2; j <= cur.left; ++j){
                tempx = cur.x + j*dir[i][0];
                tempy = cur.y + j*dir[i][1];
                if(isValid(tempx, tempy) && !visited[tempx][tempy][cur.left-j] && matrix[tempx][tempy] == 'P'){
                    q.push(Node(tempx, tempy, cur.left-j, cur.time+1));
                    visited[tempx][tempy][cur.left-j] = true;
                }
            }
        }
    }
    if(!flag)
        cout << "impossible" << endl; 
}                     

如果给visited数组加多一维的话就可以解决这个问题。

这个题目给我的思考是:考虑问题时,需要将变量的多种情况进行匹配考虑,而不能只考虑部分的配对情况,比较类似于测试的黑盒level2的组合配对。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值