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就改变标记,之后只走符合标程的下一个位置即可。


每一层的结点其实找起来也比较恶心……
代码最后有一些样例……送给泥萌……不谢……

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 #define clr(c, x) memset(c, x, sizeof(c));
  7 const int INF = 0x3f3f3f3f;
  8 typedef struct point{
  9     int x, y;
 10     bool operator < (const point& p) const{
 11         if(x == p.x) return y < p.y; // 先按照行比较大小,行相同按照列比较大小
 12         else return x < p.x;
 13     }
 14     bool operator > (const point& p) const { return p < *this; }
 15 }p;
 16 int dirx[4] = {0, 1, 0, -1};
 17 int diry[4] = {1, 0, -1, 0};
 18 const int MAXL = 1005;
 19 char maze[MAXL][MAXL];
 20 int T, n, m;
 21 int step[MAXL][MAXL]; // bfs
 22 queue<p> q;
 23 p start, goal, startDfs;
 24 int x, y, xx, yy; // x,y current; xx,yy next;
 25 int stepDfs;
 26 char ans[MAXL*MAXL+1];
 27 bool unlock[MAXL][MAXL];
 28 bool subflag;
 29 int layer;
 30 
 31 bool Inside(int xx, int yy){ // 越界判断
 32     if(xx >= 0 && xx < n && yy >= 0 && yy < m) return true;
 33     else return false;
 34 }
 35 
 36 void bfs(){ // 连续走0
 37     layer = 0;
 38     start.x = 0, start.y = 0;
 39     p current, next;
 40     clr(step, 0);
 41     while(!q.empty()) q.pop();
 42     subflag = true;
 43     step[0][0] = 1;
 44     if(maze[0][0] == '1'){
 45             subflag = false;
 46             return; // 起点就为1时就不必bfs了
 47     }
 48     q.push(start);
 49 
 50     while(!q.empty()){
 51         current = q.front();
 52         x = current.x, y = current.y;
 53         layer = layer > (x+y) ? layer : (x+y);
 54         for(int i = 0; i < 4; i++){
 55             xx = x + dirx[i], yy = y + diry[i];
 56             if(Inside(xx, yy) && maze[xx][yy] == '0' && step[xx][yy] == false){
 57                 next.x = xx, next.y = yy;
 58                 step[xx][yy] = step[x][y] + 1;
 59                 q.push(next);
 60             }
 61         }
 62         q.pop();
 63     }
 64     return;
 65 }
 66 
 67 void Result(){
 68     p current, next;
 69     clr(ans, '1');
 70     clr(unlock, 0);
 71     if(layer == n-1+m-1 && maze[0][0] == '0'){ // 如果有一条路可以走到终点且全为0
 72         puts("0"); // 只输出一个0
 73         return;
 74     }
 75     int X, Y;
 76     for(X = 0; X < n; X++){
 77         if(layer-X >= 0 && layer-X < m){
 78             Y= layer - X;
 79             if(step[X][Y] != 0){
 80                 unlock[X][Y] = true;
 81                 ans[layer] = maze[X][Y];
 82             }
 83         }
 84     }
 85     int layerSave = layer;
 86     int ansLeft = n-1 + m-1 - layer;
 87     while(ansLeft--){
 88         for(X = 0; X < n; X++){
 89             if(layer-X >= 0 && layer-X < m){
 90                 Y= layer - X;
 91                 if(unlock[X][Y] == true){ // 找到下一层可以走的符号
 92                     if(X+1 <= n-1) ans[layer+1] = ans[layer+1] < maze[X+1][Y] ? ans[layer+1] : maze[X+1][Y];
 93                     if(Y+1 <= m-1) ans[layer+1] = ans[layer+1] < maze[X][Y+1] ? ans[layer+1] : maze[X][Y+1];
 94                 }
 95             }
 96         }
 97         for(X = 0; X < n; X++){
 98             if(layer-X >= 0 && layer-X < m){
 99                 Y= layer - X;
100                 if(unlock[X][Y] == true){
101                     if(maze[X+1][Y] == ans[layer+1] && X+1 <= n-1) unlock[X+1][Y] = true;
102                     if(maze[X][Y+1] == ans[layer+1] && Y+1 <= m-1) unlock[X][Y+1] = true;
103                 }
104             }
105         }
106         layer++;
107     }
108     if(subflag) for(int i = layerSave + 1; i <= n-1+m-1; i++) printf("%c", ans[i]);
109     else for(int i = 0; i <= n-1+m-1; i++) printf("%c", ans[i]);
110     printf("\n");
111 }
112 
113 int main(){
114     scanf("%d", &T);
115     while(T--){
116         clr(maze, 0);
117         scanf("%d%d", &n, &m);
118         for(int i = 0; i < n; i++) scanf("%s", maze[i]);
119         bfs();
120         Result();
121     }
122     return 0;
123 }
124 
125 /*
126 10
127 1 1
128 1
129 1 1
130 0
131 1 5
132 00101
133 5 1
134 0
135 0
136 1
137 0
138 1
139 2 2
140 11
141 11
142 3 3
143 001
144 111
145 101
146 5 5
147 11101
148 00100
149 01000
150 01011
151 11111
152 */

 

 
posted @ 2015-08-12 21:27  快扶哀家去刷题  阅读(178)  评论(0编辑  收藏  举报