hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4
题意——
一个n*m的地图,从左上角走到右下角。
这个地图是一个01串,要求我们行走的路径形成的01串最小。
注意,串中最左端的0全部可以忽略,除非是一个0串,此时输出0。
例:
3 3
001
110
001
此图的最短路径为101。
输入——
第一行输入一个整数t,表示共有t组数据。
接下来每组第一行输入两个整数n, m。表示地图的长和宽。
接下来n行,每行m个字符。字符只有0或1。
输出——
输出一个字符串,表示最短路径。
这道题刚开始用了优先队列+大数写的bfs,然后无限爆tle,后来想了想——
首先,用优先队列时,每个节点入队的时间复杂度为log2(k),其中k为当前队列的长度。
其次,大数每次乘2的操作都要len次,每次在入队时和其他节点比较时还可能要len次,len为数的长度。
而地图最大是1000*1000的,总共的时间复杂度粗略算一下要10^6*log2(10^3)*40,刚好卡在时限上了,再乘上一个常数,就超时了,再乘上t,更超时了。
不能用优先队列,用普通队列,怎么写想了好久,在比赛结束之后又看了一下题解,发现大概有一下几种解法——
- 先搜出来从起点出发的所有0,此时起点必须是0,用bfs向4个方向搜;然后从所有0出发,寻找到终点的点,用bfs向下或向右走;然后再从终点出发,往回走,用dfs;然后就看不懂了……
- 先搜出来从起点出发的所有0,此时起点必须是0,用bfs向4个方向搜;然后在这些0中选取行号和列号相加最大的点,因为这些点距离终点最近,可以得知,这些点在同一斜行,然后从这些点所在的斜行的下一斜行开始,一行一行向下进行递推——优先选取0,对本斜行中选取的字符标记,然后对下一斜行进行递推时,只考虑可以从标记点走到的点。
当然,当对0进行搜索时,已经搜到终点,那么输出0就可以了。
我用的是第二种方法。
耗时109ms,内存4520k。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std; const int N = ; struct Node
{
int x, y;
}; int dir[][] = {{, }, {, }, {-, }, {, -}};
int sxy[N*N];
char mp[N][N];
bool vis[N][N];
int n, m, t, rt, k;
queue<Node> q0; int bfs0()
{
Node p, ps;
p.x = p.y = ;
vis[][] = ;
if(mp[][] == '') q0.push(p);
else
{
sxy[] = ;
k = ;
printf("");
return ;
}
k = ;
while(!q0.empty())
{
p = q0.front();
q0.pop();
sxy[k++] = p.x+p.y;
if(p.x == n- && p.y == m-) return ;
for(int i = ; i < ; i++)
{
int sx = p.x+dir[i][];
int sy = p.y+dir[i][];
if(sx >= && sx < n && sy >= && sy < m && !vis[sx][sy] && mp[sx][sy] == '')
{
vis[sx][sy] = ;
ps.x = sx;
ps.y = sy;
q0.push(ps);
}
}
}
return ;
} void sroot()
{
rt = ;
for(int i = ; i < k; i++) if(rt < sxy[i]) rt = sxy[i];
} void getans()
{
for(int i = rt+; i <= m+n-; i++)
{
k = ;
if(i >= n-) k = i-n+;
int tmp = ;
for(int j = k; j < m && j <= i; j++)
{
if((i-j- >= && i-j < n && j >= && vis[i-j-][j])
|| (i-j >= && i-j < n && j- >= && vis[i-j][j-]))
{
int mid = mp[i-j][j]-'';
tmp = tmp < mid ? tmp : mid;
}
}
printf("%d", tmp);
for(int j = k; j < m && j <= i; j++)
{
if((i-j- >= && i-j < n && j >= && vis[i-j-][j])
|| (i-j >= && i-j < n && j- >= && vis[i-j][j-]))
{
if(mp[i-j][j]-'' == tmp) vis[i-j][j] = ;
}
}
}
printf("\n");
} void init()
{
scanf("%d%d", &n, &m);
for(int i = ; i < n; i++) scanf("%s", mp[i]);
memset(vis, , sizeof(vis));
while(!q0.empty()) q0.pop();
} int main()
{
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
scanf("%d", &t);
while(t--)
{
init();
if(bfs0()) printf("0\n");
else
{
sroot();
getans();
}
}
return ;
}
hdu 5335 Walk Out(bfs+斜行递推) 2015 Multi-University Training Contest 4的更多相关文章
- 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+寻找路径)
Problem Description In an n∗m maze, the right-bottom corner or a written on it. An explorer gets los ...
- HDU 5335 Walk Out (BFS,技巧)
题意:有一个n*m的矩阵,每个格子中有一个数字,或为0,或为1.有个人要从(1,1)到达(n,m),要求所走过的格子中的数字按先后顺序串起来后,用二进制的判断大小方法,让这个数字最小.前缀0不需要输出 ...
- hdu 5335 Walk Out (搜索)
题目链接: hdu 5335 Walk Out 题目描述: 有一个n*m由0 or 1组成的矩形,探险家要从(1,1)走到(n, m),可以向上下左右四个方向走,但是探险家就是不走寻常路,他想让他所走 ...
- HDU 5459 Jesus Is Here(递推)
http://acm.hdu.edu.cn/showproblem.php?pid=5459 题意: S(1) = c,S(2) = ff, S(3) = cff,之后S(i) = S(i-1)+S( ...
- HDU 4834 JZP Set(数论+递推)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 一个{1, ..., n}的子集S被称为JZP集,当且仅当对于任意S中的两个数x,y,若(x+y)/2为整数,那么(x+y)/2也属于S.例如,n=3,S={1 ...
- HDU 2050 折线分割平面 (递推)
题意:略. 析:多写几个就找到规律了,第1条是2,2条时是7个,3条时是16,4条时是29,.... 那么规律就出来了2 * n * n + 1 - n; 也可以递推,第n条折线的两条边都与前n-1条 ...
- HDU - 6172:Array Challenge (BM线性递推)
题意:给出,三个函数,h,b,a,然后T次询问,每次给出n,求sqrt(an); 思路:不会推,但是感觉a应该是线性的,这个时候我们就可以用BM线性递推,自己求出前几项,然后放到模板里,就可以求了. ...
- HDU - 2604 矩阵快速幂 字符串递推 两种解法
记dp[i]为长度i且符合题意的方案数,dp[n]就是解 符合方案的是不含fmf和fff子串的字符串 考虑如何从前面几项递推出后面第i项 (★表示存在生成的非法方案)←其实没啥用处 i=1时 m③ f ...
随机推荐
- 如何处理JSON中的特殊字符
JSON 是适用于 Ajax 应用程序的一种有效格式,原因是它使 JavaScript 对象和字符串值之间得以快速转换.由于 Ajax 应用程序非常适合将纯文本发送给服务器端程序并对应地接收纯文本,相 ...
- hdu 4417 Super Mario 离线线段树
思路:将点按值从小到大排序,询问按h从小到大排序. 在建立线段树,按h的大小更新树并得到该次查询的结果! 代码如下: #include<iostream> #include<stdi ...
- cogs 自己出的题目 题解报告
第一题很简单嘛,就是裸的动态树分治嘛 对于每一层的重心维护子树路径的信息和子树到上一层重心的点的信息 空间复杂度O(nlogn) 对于每一层我们按dis排序,之后记录军队数量的前缀和 查询的时候我们只 ...
- BZOJ 3720 gty的妹子树
块状树裸题 块状树: 首先对树进行分块,分出的每一块都是一个连通块 通常的分块的方式如下: 1.父亲所在块不满,分到父亲所在块中 2.父亲所在块满,自己单独开一个块 (貌似有更为优越的分块方式? 注意 ...
- FireMonkey支持的机型
酷派5890(android 4.1.2) 从截图上看,正常.不知道为啥说不行.海信 T96(android 4.0.3) CPU 不支持 NEON.没辙.摩托罗拉XT885(android 4.0. ...
- Android:创建Android工程
创建Android工程,在Eclipse左栏右键 new->project.. (版本不一样,名字会有所区别) 然后选择Android下的Android application projec ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)
这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...
- MTK6577+Android4.04编译
MTK6577+Android4.04编译 编译命令 ./mk new 出错信息如下: **********checkingEnv************ Your building environm ...
- 客户视角:Oracle ETL工具ODI
客户视角:Oracle ETL工具ODI 数据集成已成为企业在追求市场份额中的关键技术组件,与依靠手工编码的方式不同,越来越多的企业选择完整的数据集成解决方案来支持其IT战略,从大数据分析到云平台的集 ...
- Windows XP搜索功能 "包含文字" 搜索不到内容的解决办法
Windows开始菜单 -- 运行 -- regedit -- 确定,编辑注册表 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet\Control\ContentIndex 右 ...