题目就是在一个只有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(" "); 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 */