zoukankan      html  css  js  c++  java
  • joj 2558 Ocean Currents 特别的广搜 yongmou

    题意:

      一个R*C的海面,1<= R、C<=1000,上面每个点都有八个方向之一的current,顺着流走一个单位cost 0,不顺着走一个单位cost 1。计算由一个初始位置到结束位置最小的cost.

    思路:

      本来用A*,TLE,想想主要是因为A*考虑访问过的顶点,其实,这个题A*用的很憋屈,启发函数必须设成0。后来还是用了BFS,用两个队列,先把cost为0的全部入队列1,然后由队列1中的点扩展cost为1的点入队列2,直到队列1为空;再由队列2中点扩展cost为2的点,循环,直到找到目标节点。

      一般的BFS求最短路径,需要一个记录顶点路径长度的表,但是,这种用两个队列的方式,就不需要这个表,而只用一个变量即可。代码中,用两个指针来操作队列就可以了,内层循环结束了swap一下两个指针。

    代码:

    代码
    #include <cstdio>
    #include
    <queue>
    using namespace std;

    struct position{
    int x, y;
    };

    #define MAX 1000

    int R, C;
    char mt[MAX+1][MAX+4];
    position S, T;
    int move[8][2]={{-1,0}, {-1, 1}, {0,1}, {1,1},
    {
    1,0}, {1, -1}, {0, -1}, {-1, -1}};


    bool is_valid(const position & v){
    return (1<=v.x && v.x<=R && 1<=v.y && v.y <=C);
    }

    bool visited[MAX+1][MAX+1];
    int BFS(){
    for(int i=1; i<=R; ++i)
    for(int j=1; j<=C; ++j)
    visited[i][j]
    = false;
    int dist, cur;
    position u, v;
    queue
    <position> que1, que2;
    queue
    <position> *popen, *pnext;
    dist
    = 0;
    popen
    = &que1;
    pnext
    = &que2;

    v
    = S;
    while(is_valid(v) && !visited[v.x][v.y]){
    if(v.x == T.x && v.y == T.y)
    return dist;
    popen
    ->push(v);
    visited[v.x][v.y]
    = true;
    cur
    = mt[v.x][v.y];
    v.x
    += move[cur][0];
    v.y
    += move[cur][1];
    }
    while(true){
    ++dist;
    while(!popen->empty()){
    u
    = popen->front();
    popen
    ->pop();
    for(int i=0; i<8; ++i){
    if(i == mt[u.x][u.y])
    continue;
    v.x
    = u.x + move[i][0];
    v.y
    = u.y + move[i][1];
    while(is_valid(v) && !visited[v.x][v.y]){
    if(v.x == T.x && v.y == T.y)
    return dist;
    pnext
    ->push(v);
    visited[v.x][v.y]
    = true;
    cur
    = mt[v.x][v.y];
    v.x
    += move[cur][0];
    v.y
    += move[cur][1];
    }
    }
    }
    swap(popen, pnext);
    }
    }

    int main(){
    // freopen("in", "r", stdin);
    while(scanf("%d %d", &R, &C) != EOF){
    for(int i=1; i<=R; ++i)
    scanf(
    "%s", &mt[i][1]);
    for(int i=1; i<=R; ++i)
    for(int j=1; j<=C; ++j)
    mt[i][j]
    -= '0';
    int m, d;
    scanf(
    "%d", &m);
    for(int i=0; i<m; ++i){
    scanf(
    "%d %d %d %d", &S.x, &S.y, &T.x, &T.y);
    d
    = BFS();
    printf(
    "%d\n", d);
    }
    printf(
    "\n");
    }
    return 0;
    }
  • 相关阅读:
    如何增加按钮的点击间隔时间
    如何增加button的点击范围
    定时器Timer的使用
    NSCache
    GCD和NSOperation的区别
    NSOperation实现线程间通信
    NSOperation添加操作依赖和监听
    自定义NSOperation
    NSOperation的多线程
    单例的实现(完整版代码)
  • 原文地址:https://www.cnblogs.com/liyongmou/p/1783396.html
Copyright © 2011-2022 走看看