题目链接:
题意:
1000X1000的地图, 问通过四个方向从(1,1)走到(1000,1000)所经过的最小二进制序列是多少.
解题思路:
首先应该通过bfs找到 (1,1)能走到的值为0且最接近右下角的位置 (x+y值最大 ,有多个全部保存)
这样就能保证接下来找的序列是最短的
接下来每一步的最优策略只有两种可能: 往右或往下,也就是说下一层的新节点都在同一条斜线上
而如果遇到0,那么是一定要走的 保存下来,同时如果当前层有0和1,则含1的节点不需要继续扩展
在寻找终点的过程中每次输出当前层的最小值,最后就能得到 最小的二进制序列
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #define maxn 1005 using namespace std; struct node { int x,y; } head,t; int map[maxn][maxn]; int vis[maxn][maxn]; int dir[4][2]= {1,0,0,1,-1,0,0,-1}; int n,m; int ok() { if(t.x<1||t.y<1||t.x>n||t.y>m||vis[t.x][t.y]) return 0; return 1; } void bfs() { vector<node>w; int maxx=0; memset(vis,0,sizeof(vis)); queue<node>q; q.push((node){0,1}); //从图外开始 while(!q.empty()) { head=q.front(); q.pop(); if(head.x+head.y>maxx) { if(head.x==n&&head.y==m) // 有一条全是0的路径 { printf("0\n"); return; } maxx=head.x+head.y; w.clear(); w.push_back(head); } if(head.x+head.y==maxx) w.push_back(head); for(int i=0; i<4; i++) { t.x=head.x+dir[i][0]; t.y=head.y+dir[i][1]; if(!ok()||map[t.x][t.y]==1) continue; vis[t.x][t.y]=1; q.push(t); } } vector<node>q2[2]; int now=0,next=1; int flag; if(map[1][1]!=1){ for(int i=0; i<w.size(); i++) q2[0].push_back(w[i]); } else //没有前导0 q2[0].push_back((node){0,1}); while(1) //层次遍历 { flag=0; for(int i=0;i<q2[now].size();i++) { head=q2[now][i]; for(int i=0;i<2;i++) { t.x=head.x+dir[i][0]; t.y=head.y+dir[i][1]; if(!ok()||vis[t.x][t.y]) continue; vis[t.x][t.y]=1; if(t.x==n&&t.y==m) { printf("%d\n",map[t.x][t.y]); return; } if(map[t.x][t.y]==0) { if(!flag) q2[next].clear(); flag=1; q2[next].push_back(t); } else if(!flag&&map[t.x][t.y]==1) q2[next].push_back(t); } } q2[now].clear(); if(flag) //该层有0 printf("0"); else printf("1"); swap(now,next); } } int main() { // freopen("in.txt","r",stdin); int T; char str[maxn]; int len; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%s",str+1); len=strlen(str+1); for(int j=1; j<=len; j++) map[i][j]=str[j]-'0'; } bfs(); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-06 15:26:46