HDOJ 5335 Walk Out 【bfs 貪心 斜行dp】

HDOJ 5335 Walk Out 【bfs 貪心 斜行dp】

題目鏈接 http://acm.hdu.edu.cn/showproblem.php?pid=5335


題目就是在一個只有0 1 的矩陣裏從左上角走到右下角
每走一步記錄當前的座標值 輸出所有結果中數值最小的結果 輸出時去掉前綴零。
很明顯如果有全部是0的部分,直接輸出0就可以了
前面不管有多少個0都是可以去掉的
從1開始之後,數字的長度就固定了
而長的數總比短的數大
所以先bfs只走0走到最深處
之後貪心,如果下一步可以走0就走0,走到最後輸出即可


實現的細節是如果開始是1的話就可以不必進入bfs
以及bfs如果可以到達右下角的出口就可以直接輸出0
(注意只有一個數據的情況,如果是0。。。)
其他的情況先將最右下角可以到達的0都標記成可以達到
之後按照層數(layer = i+j) 依次遞增找到周圍可達的下一個點(只走右邊或者下邊)如果有0就改變標記,之後只走符合標程的下一個位置即可。


每一層的結點其實找起來也比較噁心……
代碼最後有一些樣例……送給泥萌……不謝……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define clr(c, x) memset(c, x, sizeof(c));
const int INF = 0x3f3f3f3f;
typedef struct point{
    int x, y;
    bool operator < (const point& p) const{
        if(x == p.x) return y < p.y; // 先按照行比較大小,行相同按照列比較大小
        else return x < p.x;
    }
    bool operator > (const point& p) const { return p < *this; }
}p;
int dirx[4] = {0, 1, 0, -1};
int diry[4] = {1, 0, -1, 0};
const int MAXL = 1005;
char maze[MAXL][MAXL];
int T, n, m;
int step[MAXL][MAXL]; // bfs
queue<p> q;
p start, goal, startDfs;
int x, y, xx, yy; // x,y current; xx,yy next;
int stepDfs;
char ans[MAXL*MAXL+1];
bool unlock[MAXL][MAXL];
bool subflag;
int layer;

bool Inside(int xx, int yy){ // 越界判斷
    if(xx >= 0 && xx < n && yy >= 0 && yy < m) return true;
    else return false;
}

void bfs(){ // 連續走0
    layer = 0;
    start.x = 0, start.y = 0;
    p current, next;
    clr(step, 0);
    while(!q.empty()) q.pop();
    subflag = true;
    step[0][0] = 1;
    if(maze[0][0] == '1'){
            subflag = false;
            return; // 起點就爲1時就不必bfs了
    }
    q.push(start);

    while(!q.empty()){
        current = q.front();
        x = current.x, y = current.y;
        layer = layer > (x+y) ? layer : (x+y);
        for(int i = 0; i < 4; i++){
            xx = x + dirx[i], yy = y + diry[i];
            if(Inside(xx, yy) && maze[xx][yy] == '0' && step[xx][yy] == false){
                next.x = xx, next.y = yy;
                step[xx][yy] = step[x][y] + 1;
                q.push(next);
            }
        }
        q.pop();
    }
    return;
}

void Result(){
    p current, next;
    clr(ans, '1');
    clr(unlock, 0);
    if(layer == n-1+m-1 && maze[0][0] == '0'){ // 如果有一條路可以走到終點且全爲0
        puts("0"); // 只輸出一個0
        return;
    }
    int X, Y;
    for(X = 0; X < n; X++){
        if(layer-X >= 0 && layer-X < m){
            Y= layer - X;
            if(step[X][Y] != 0){
                unlock[X][Y] = true;
                ans[layer] = maze[X][Y];
            }
        }
    }
    int layerSave = layer;
    int ansLeft = n-1 + m-1 - layer;
    while(ansLeft--){
        for(X = 0; X < n; X++){
            if(layer-X >= 0 && layer-X < m){
                Y= layer - X;
                if(unlock[X][Y] == true){ // 找到下一層可以走的符號
                    if(X+1 <= n-1) ans[layer+1] = ans[layer+1] < maze[X+1][Y] ? ans[layer+1] : maze[X+1][Y];
                    if(Y+1 <= m-1) ans[layer+1] = ans[layer+1] < maze[X][Y+1] ? ans[layer+1] : maze[X][Y+1];
                }
            }
        }
        for(X = 0; X < n; X++){
            if(layer-X >= 0 && layer-X < m){
                Y= layer - X;
                if(unlock[X][Y] == true){
                    if(maze[X+1][Y] == ans[layer+1] && X+1 <= n-1) unlock[X+1][Y] = true;
                    if(maze[X][Y+1] == ans[layer+1] && Y+1 <= m-1) unlock[X][Y+1] = true;
                }
            }
        }
        layer++;
    }
    if(subflag) for(int i = layerSave + 1; i <= n-1+m-1; i++) printf("%c", ans[i]);
    else for(int i = 0; i <= n-1+m-1; i++) printf("%c", ans[i]);
    printf("\n");
}

int main(){
    scanf("%d", &T);
    while(T--){
        clr(maze, 0);
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) scanf("%s", maze[i]);
        bfs();
        Result();
    }
    return 0;
}

/*
10
1 1
1
1 1
0
1 5
00101
5 1
0
0
1
0
1
2 2
11
11
3 3
001
111
101
5 5
11101
00100
01000
01011
11111
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章