题意——

一个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,更超时了。

不能用优先队列,用普通队列,怎么写想了好久,在比赛结束之后又看了一下题解,发现大概有一下几种解法——

  1. 先搜出来从起点出发的所有0,此时起点必须是0,用bfs向4个方向搜;然后从所有0出发,寻找到终点的点,用bfs向下或向右走;然后再从终点出发,往回走,用dfs;然后就看不懂了……
  2. 先搜出来从起点出发的所有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的更多相关文章

  1. HDU 5335 Walk Out BFS 比较坑

    H - H Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status ...

  2. 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 ...

  3. HDU 5335 Walk Out (BFS,技巧)

    题意:有一个n*m的矩阵,每个格子中有一个数字,或为0,或为1.有个人要从(1,1)到达(n,m),要求所走过的格子中的数字按先后顺序串起来后,用二进制的判断大小方法,让这个数字最小.前缀0不需要输出 ...

  4. hdu 5335 Walk Out (搜索)

    题目链接: hdu 5335 Walk Out 题目描述: 有一个n*m由0 or 1组成的矩形,探险家要从(1,1)走到(n, m),可以向上下左右四个方向走,但是探险家就是不走寻常路,他想让他所走 ...

  5. 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( ...

  6. 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 ...

  7. HDU 2050 折线分割平面 (递推)

    题意:略. 析:多写几个就找到规律了,第1条是2,2条时是7个,3条时是16,4条时是29,.... 那么规律就出来了2 * n * n + 1 - n; 也可以递推,第n条折线的两条边都与前n-1条 ...

  8. HDU - 6172:Array Challenge (BM线性递推)

    题意:给出,三个函数,h,b,a,然后T次询问,每次给出n,求sqrt(an); 思路:不会推,但是感觉a应该是线性的,这个时候我们就可以用BM线性递推,自己求出前几项,然后放到模板里,就可以求了. ...

  9. HDU - 2604 矩阵快速幂 字符串递推 两种解法

    记dp[i]为长度i且符合题意的方案数,dp[n]就是解 符合方案的是不含fmf和fff子串的字符串 考虑如何从前面几项递推出后面第i项 (★表示存在生成的非法方案)←其实没啥用处 i=1时 m③ f ...

随机推荐

  1. 漫谈CGI FastCGI WSGI

    作者:auxten链接:https://zhuanlan.zhihu.com/p/20054757来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. CGI(Common ...

  2. How to define Servlet filter order of execution using annotations

    If we define Servlet filters in web.xml, then the order of execution of the filters will be the same ...

  3. Calling Lua From a C Program

    Introduction From a running C program, you can call a Lua script. The C program can pass arguments t ...

  4. Ubuntu环境下手动配置HBase0.94.25

    /×××××××××××××××××××××××××××××××××××××××××/ Author:xxx0624 HomePage:http://www.cnblogs.com/xxx0624/ ...

  5. Android 近百个项目的源代码

    Android 近百个项目的源代码 Android PDF 阅读器 http://sourceforge.net/projects/andpdf/files/个人记账工具 OnMyMeans http ...

  6. sql查询数据库中所有表的记录条数,以及占用磁盘空间大小。

    SELECT TableName = obj.name, TotalRows = prt.rows, [SpaceUsed(KB)] = SUM(alloc.used_pages)* FROM sys ...

  7. http://www.aboutyun.com/thread-8792-1-1.html

    http://www.aboutyun.com/thread-8792-1-1.html

  8. Ubuntu 14.04 + Linux 3.14.34 系统调用实现文件拷贝

    采用 64位系统, ubuntu 14.04 + 新内核linux-3.14.34 下载地址https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.1 ...

  9. CentOS安装VSFTP及配置用户

    第一步,安装vsftp # 1.以管理员(root)身份执行以下命令 yum install vsftpd # 2.设置开机启动vsftpd ftp服务 chkconfig vsftpd on # 3 ...

  10. get Status canceled 请求被取消

    1.chrome浏览器下状况: 2.环境: 一个页面A下 包含一个 iframe ,在子页面中用js点击A页面下的链接替换iframe内容脚本如下: window.parent.document.ge ...