1. 程式人生 > >Codeforces Round #516 D. Labyrinth

Codeforces Round #516 D. Labyrinth

地址:http://codeforces.com/contest/1064/problem/D

搜尋題,用dfs會超,不能剪枝,因為這個一個cell會被多次訪問;
但是一般像遇到像求最短什麼的,就用bfs,用bfs也可以,但是要有個優先順序,因為可能搜尋路徑會因為之前被搜尋過而截斷
這個例子:

10 10
10 4
10 9
...*******
.*.*******
.*.*******
.*.*******
.*.*******
.*.*......
.*.*.*****
.*........
.********.
..........

應該修改搜尋策略,l+r可搜尋寬度較大的先走,那麼就要用優先隊列了,所以給我個教訓,其實寬搜用優先佇列就好啊,用的時間又短又好用。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const int N = 2005;

char s[N][N];
bool vis[N][N];
typedef struct Node{
    int x,y;
    int l,r;
    friend bool operator < (const Node &p,const Node &q){
        return p.l + p.r < q.l + q.r;
    }
}Node;
int n,m,x,y,r,c;

int col[5] = {-1,1,0,0};
int con[5] = {0,0,-1,1};

bool judge(int i,int j)
{
    if(i < 1 || j < 1)
        return false;
    if(i > n || j > m)
        return false;
    return true;
}

int main()
{
    scanf("%d %d",&n,&m);
    scanf("%d %d",&r,&c);
    scanf("%d %d",&x,&y);
    for(int i = 1;i <= n;++i){
        scanf("%s",s[i] + 1);
    }
    memset(vis,false,sizeof(vis));
    priority_queue<Node>que;
    que.push((Node){r,c,x,y});
    vis[r][c] = true;
    while(!que.empty())
    {
        Node tmp = que.top();
        que.pop();
        int tx = tmp.x,ty = tmp.y;
        int l = tmp.l,r = tmp.r;
        //cout << tx << " " << ty << " " << l << " " << r << endl;
        for(int i = 0;i < 4;++i){
            int x1 = tx + col[i];
            int y1 = ty + con[i];
            if(judge(x1,y1) && !vis[x1][y1] && s[x1][y1] != '*'){
                if(i == 2){
                    if(l - 1 < 0) continue;
                    vis[x1][y1] = true;
                    que.push((Node){x1,y1,l - 1,r});
                }else if(i == 3){
                    if(r - 1 < 0) continue;
                    vis[x1][y1] = true;
                    que.push((Node){x1,y1,l,r - 1});
                }else{
                    vis[x1][y1] = true;
                    que.push((Node){x1,y1,l,r});
                }
            }
        }
    }
//    for(int i = 1;i <= n;++i){
//        for(int j = 1;j <= m;++j){
//            printf("%d ",vis[i][j]);
//        }
//        printf("\n");
//    }
    int sum = 0;
    for(int i = 1;i <= n;++i){
        for(int j = 1;j <= m;++j){
            if(vis[i][j]) sum++;
        }
    }
    printf("%d\n",sum);
    return 0;
}

大佬的做法,用雙端佇列,上下走的放在佇列頭優先走,左右走的放在末尾最後走