HDU 5335 Walk Out (BFS,技巧)
题意:有一个n*m的矩阵,每个格子中有一个数字,或为0,或为1。有个人要从(1,1)到达(n,m),要求所走过的格子中的数字按先后顺序串起来后,用二进制的判断大小方法,让这个数字最小。前缀0不需要输出!!
思路:主要考虑的是BFS解决。
如果grid[1,1]=1,那么这个二进制的位数也就定下来了,是n+m-1,很好解决,每个格子就只能往下或者往右,否则长度一定超过n+m+1,必定不是最优。
如果grid[1,1]=0,那么可能会出现绕了一个S型到终点的结果为0而已。所以不能用老办法,要先预处理一下。处理方式是,用BFS将所有grid[1,1]可达的0点标记出来,找出其中距离终点最近的那些0点(可能多个),如果他们的下和右边的点为1,这些点都进队,再用上边方式BFS即可求得答案(上面只是1个起点,这边有多个起点,不影响正确性)。
答案在哪?其实在BFS时每一层只能是0点或者是1点,为什么呢?如果有0点的话,还需要选择1点的吗?别忘了二进制的位数是固定了,选0肯定比选1要好,则在没有0的情况下再选1的。 在遍历时按层遍历,遍历到的点先分到两个集合A0和B1中,择所需即可,所以在遍历第i层时第i位的答案也就决定了。这是剪枝!
注意考虑只有1个点,2个点和S形等各种情况。
#include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL unsigned long long
using namespace std;
const int N=;
int n, m;
char grid[N][N];
vector<int> ans;
int inq[N][N]; void BFS(deque<pii> &que)
{
ans.push_back();
while(!que.empty())
{
deque<pii> que0, que1; //两种到达的方式,只取其一
int siz=que.size();
for(int i=; i<siz; i++) //被更新的都是同一源头的。
{
int a=que.front().first;
int b=que.front().second;
que.pop_front(); if( a+<=n && !inq[a+][b] ) //下:要么你无路径可达,要么我比你小,我才更新你
{
if(grid[a+][b]=='') que0.push_back(make_pair(a+,b));
else que1.push_back(make_pair(a+,b));
}
if( b+<=m && !inq[a][b+] ) //右
{
if(grid[a][b+]=='') que0.push_back(make_pair(a,b+));
else que1.push_back(make_pair(a,b+));
}
inq[a+][b]=inq[a][b+]=;
} if(!que0.empty()) ans.push_back();
else ans.push_back(); if(!que0.empty()) que.insert(que.end(), que0.begin(), que0.end() );
else que.insert(que.end(), que1.begin(), que1.end() );
}
} int cal()
{
memset(inq, , sizeof(inq)); deque<pii> que;que.push_back( make_pair(,));
if(grid[][]=='') //若起点为0,找到所有离终点最近的前缀0
{
inq[][]=;
while(!que.empty())
{
int siz=que.size();
for(int i=; i<siz; i++) //按层来BFS,按层记录最优答案
{
int a=que.front().first;
int b=que.front().second;
que.pop_front(); if(a+<=n && !inq[a+][b] && grid[a+][b]=='') que.push_back(make_pair(a+,b));
if(a-> && !inq[a-][b] && grid[a-][b]=='') que.push_back(make_pair(a-,b)); if(b+<=m && !inq[a][b+] && grid[a][b+]=='') que.push_back(make_pair(a,b+));
if(b-> && !inq[a][b-] && grid[a][b-]=='') que.push_back(make_pair(a,b-)); inq[a+][b]=inq[a-][b]=inq[a][b+]=inq[a][b-]=; //防止重复进队
}
}
int min_dis=INF;
for(int i=; i<=n; i++) //求最近的0距离终点的最小距离
{
for(int j=; j<=m; j++)
{
if(inq[i][j]&&grid[i][j]=='')
min_dis=min(min_dis, n+m-j-i);
}
}
if(grid[n][m]=='' && min_dis==) return ; //有0路可达终点
for(int i=; i<=n; i++) //扫出距离为min_dis的所有0点
for(int j=; j<=m; j++)
if(inq[i][j] && grid[i][j]=='' && min_dis==n+m-j-i && n+m-i-j!= )
que.push_back(make_pair(i,j)); memset(inq,,sizeof(inq));
int siz=que.size();
for(int i=; i<siz; i++) //将所有0点的下和右为1的点进队
{
int a=que.front().first;
int b=que.front().second;
que.pop_front();
if(a+<=n&&!inq[a+][b]&&grid[a+][b]=='') que.push_back(make_pair(a+,b));
if(b+<=m&&!inq[a][b+]&&grid[a][b+]=='') que.push_back(make_pair(a,b+));
inq[a+][b]=inq[a][b+]=;
}
}
BFS(que);
return ans.size();
} int main()
{
freopen("input.txt", "r", stdin);
int t, a, b;
char c;
cin>>t;
while(t--)
{
ans.clear();
scanf("%d %d",&n,&m); for(int i=; i<=n; i++) //输入要注意
for(int j=; j<=m; j++)
{
c=getchar();
if(c==''||c=='' ) grid[i][j]=c;
else j--;
}
int s=cal();
if(s==) printf("");
else for(int i=; i+<ans.size(); i++) printf("%d",ans[i]);//最后一个数字多余
printf("\n");
}
return ;
}
AC代码
HDU 5335 Walk Out (BFS,技巧)的更多相关文章
- HDU 5335 Walk Out BFS 比较坑
H - H Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status ...
- hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4
题意—— 一个n*m的地图,从左上角走到右下角. 这个地图是一个01串,要求我们行走的路径形成的01串最小. 注意,串中最左端的0全部可以忽略,除非是一个0串,此时输出0. 例: 3 3 001 11 ...
- hdu 5335 Walk Out(bfs+寻找路径)
Problem Description In an n∗m maze, the right-bottom corner or a written on it. An explorer gets los ...
- hdu 5335 Walk Out (搜索)
题目链接: hdu 5335 Walk Out 题目描述: 有一个n*m由0 or 1组成的矩形,探险家要从(1,1)走到(n, m),可以向上下左右四个方向走,但是探险家就是不走寻常路,他想让他所走 ...
- HDU 5335——Walk Out——————【贪心】
Walk Out Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- HDU 5335 Walk Out(多校)
Walk Out Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- hdu 5335 Walk Out (2015 Multi-University Training Contest 4)
Walk Out Time Limit: 2000/10 ...
- hdu 5335 Walk Out 搜索+贪心
Walk Out Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total S ...
- 2015 Multi-University Training Contest 4 hdu 5335 Walk Out
Walk Out Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
随机推荐
- HDU4831&&4832&&4834
好久没打代码啦,今天lu一发百度之星,感觉还是学到不少东西的,写点收获. 第一题就是现在的HDU4831啦,题意很清楚,我一开始以为休息区也可以变为风景区,所以就不敢敲了,后来才得知数据里只会改风景区 ...
- (转)单机上配置hadoop
哈哈,几天连续收到百度两次电话,均是利好消息,于是乎不知不觉的自己的工作效率也提高了,几天折腾了好久终于在单机上配置好了hadoop,然后也成功的运行了一个用例,耶耶耶耶耶耶. 转自:http://w ...
- win7建wifi 热点,附wifi小工具
首先申明:1)以下操作均在管理员身份下操作,其他用户下请亲测. 2)具备无线网卡,并且已经安装好了驱动. 1.打开命令行:输入netsh wlan set hostedn ...
- iOS多线程的初步研究(十)-- dispatch同步
GCD提供两种方式支持dispatch队列同步,即dispatch组和信号量. 一.dispatch组(dispatch group) 1. 创建dispatch组 dispatch_group_t ...
- 深入浅出ES6(十一):生成器 Generators,续篇
作者 Jason Orendorff github主页 https://github.com/jorendorff 欢迎回到深入浅出ES6专栏,望你在ES6探索之旅中收获知识与快乐!程序员们在工作 ...
- 自制 JS.format带分页索引
//第一参数是:Json对象,第二个是 序号 第三个 页数 第四 当前页数String.prototype.format = function (args, sid, pagesi ...
- MongoDB (三) MongoDB 安装
MongoDB安装在Windows上 在 Windows上,首先要安装 MongoDB下载最新发布的MongoDB: http://www.mongodb.org/downloads 确保得到正确的版 ...
- Android核心分析之十六Android电话系统-概述篇
Android电话系统之概述篇 首先抛开Android的一切概念来研究一下电话系统的最基本的描述.我们的手机首先用来打电话的,随后是需要一个电话本,随后是PIM,随后是网络应用,随后是云计算,随后是想 ...
- C++语言,统计一篇英文文章中的单词数(用正则表达式实现)
下面的例子展示了如何在C++11中,利用regex_search()统计一篇英文文章中的单词数: #include <iostream> #include <regex> #i ...
- (转载)怎么写tab?
演示地址:http://www.adanghome.com/js_demo/3/ =========================================================== ...