HDOJ 5335 Walk Out 【bfs 貪心 斜行dp】
題目就是在一個只有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
*/