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
*/