二进制迷宫 贪心 BFS
来源:互联网 发布:win10网络重置命令 编辑:程序博客网 时间:2024/05/22 15:07
搜索专项训练赛 二进制迷宫
题目大意
给出一个n*m的图,数字要么是0要么是1。从左上角坐标为(1,1)的格子出发,走到右下角的坐标为(n,m)的格子,可以沿上下左右四个方向行走。每到一个格子,就记录下里面的数字。到达终点的时候,将得到一个由0和1构成的序列,把这个序列看做一个二进制数(可以含前导零)。要求这个二进制数尽可能小,计算并输出这个二进制数。
数据范围
对于30%的数据:1≤n,m≤100
对于100%的数据:1≤n,m≤1000
考试的时候并没有说是搜索专项训练赛,所以一开始想到DP是很正常的,竟然有同学使用了string类型的DP数组,真是开了眼界(然而这样AC不了)。
首先容易想到,去掉前导零后,这个二进制数的位数要尽量少,在保证位数最少的情况下,尽量让高位选0。这个贪心是显然正确的,但是怎样知道位数最小值是多少?从哪里开始贪心?
题目中上下左右都可以行走,如果是DP的话状态不是很好转移。如果说只能向下或向右走容易让我们想到DP,那么多个方向都能行走容易让我们想到BFS。
其实,“只能向下或向右走”也能指向正解。如果当前已经有1出现了,那么就只能向下或向右走了,因为不这样做会使位数增多。注意到在只能向下或向右走的前提下,走到终点的步数是一定的,是能够算出来的。保证位数最少,可以通过BFS找到离终点“最近”的一个或者多个0。
接下来就要从这些0出发找到最优解。只能向下或向右走,此时当然可以用DP了,但是用string类型的DP数组?其实还是BFS就可以了。开一个答案数组,记录答案的每一位上填0还是填1,这样就可以剪掉上一步不可能达到最优解的情况,具体实现见代码。
时间复杂度
代码:
#include<stdio.h>#include<queue>#include<algorithm>#define MAXN 1005using namespace std;int N,M,id[MAXN][MAXN];char Map[MAXN][MAXN];int Ans[MAXN*2];bool vis[MAXN][MAXN];struct node{int x,y,step,v;};//x,y表示位置,step记录从符合要求的0开始已经走了多少步,v记录上一步的权值queue<node>Q;int Max=1;int dx[4]={1,0,0,-1},dy[4]={0,1,-1,0};void BFS(){ vis[1][1]=true; if(Map[1][1]=='1')return; node tmp,head; tmp.x=1;tmp.y=1; Q.push(tmp); int k,a,b,ta,tb; while(Q.size()) { head=Q.front();Q.pop(); a=head.x;b=head.y; for(k=0;k<4;k++) { ta=a+dx[k];tb=b+dy[k]; if(!vis[ta][tb]&&Map[ta][tb]=='0'&&ta&&tb&&ta<=N&&tb<=M) { vis[ta][tb]=true; Max=max(Max,ta+tb-1);//找“最靠近终点”的0 tmp.x=ta;tmp.y=tb; Q.push(tmp); } } }}bool mark[MAXN][MAXN];void GetAns(){ int i,j,x,y,a,b,ta,tb,tv; node tmp,head; for(i=1;i<=N;i++) { x=i;y=Max-x+1; if(vis[x][y]&&y>0&&x>0&&y<=M) { tmp.x=x;tmp.y=y;tmp.step=0;tmp.v=0; Q.push(tmp); } }//多个满足条件的0,全部入队 while(Q.size()) { head=Q.front();Q.pop(); if(head.v>Ans[head.step])continue;//剪掉不能得到最优解的情况 a=head.x;b=head.y; for(i=0;i<2;i++) { ta=a+dx[i];tb=b+dy[i]; if(ta&&tb&&ta<=N&&tb<=M) { tv=Map[ta][tb]-'0'; if(Ans[head.step+1]>=tv) { Ans[head.step+1]=tv; tmp.step=head.step+1; tmp.x=ta;tmp.y=tb; tmp.v=tv; if(!mark[ta][tb])Q.push(tmp),mark[ta][tb]=true;//防止同一个点多次进队 } } } }}int main(){ int i,j,tot=0; scanf("%d%d",&N,&M); for(i=1;i<=N;i++)scanf("%s",&Map[i][1]); BFS(); for(i=0;i<=N+M-Max;i++)Ans[i]=1e9; GetAns(); if(Map[1][1]=='1')putchar('1'); for(i=1;i<=N+M-Max-1;i++)printf("%d",Ans[i]); if(Map[1][1]=='0'&&N+M-Max-1==0)putchar('0'); //答案就是0,不能输出空串}
- 二进制迷宫 贪心 BFS
- HNUST 1454: 挑战ACM迷宫(BFS+贪心)
- BFS~~~迷宫
- BFS(迷宫)
- 迷宫-BFS
- BFS------迷宫
- 迷宫-BFS
- hdu1728 逃离迷宫(bfs)
- POJ3984 迷宫问题 BFS
- 经典迷宫问题BFS
- 迷宫问题 bfs
- 迷宫问题BFS暴搜
- BFS走迷宫
- BFS | 3984 | 迷宫问题
- HDU1728:逃离迷宫(BFS)
- hncu1102:迷宫问题(BFS)
- POJ3984 迷宫问题 BFS
- hdu1728逃离迷宫(bfs)
- 弱校胡策 大逃亡(BFS灌水+二分答案)
- java获取cpu使用率/内存使用率/硬盘的使用率
- 科学计算库Numpy-矩阵操作
- poj2766
- share network connection on windows
- 二进制迷宫 贪心 BFS
- 单例模式解决多线程的问题
- caioj·1060: 背包6(含价值的填满型 完全 背包)
- scala入门初介
- linux
- Spring 框架
- 装饰器,生成器,迭代器
- Java上机实验之接口
- 通过git工具上传代码至GitHub