hdu5335 Walk Out (递推||广搜)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5335

题意:给你N*M的01矩阵,求从(1,1)位置走到(N,M)的最小二进制数,输出不含前导0。

分析:为了不让当前位置向上走,可以先将所有的起点预处理出来。当(1,1)为1,那么起点只有一个,就是(1,1);当(1,1)为0,起点就是从(1,1)可达的并且只走0的这些点,然后把这些起点离终点最近的所有点选出来,那么这些起点在一条斜线上,而且只能向右或者向下走。然后在斜线上递推,有0可走就只走0,否则走1。(也可以bfs搜,不过我写得有问题)

代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1006;
char str[maxn][maxn];
bool visit[maxn][maxn];
int ans[maxn*maxn+10],len,M,N;
struct node
{
	int x,y;
	node(int a=0,int b=0)
	:x(a),y(b){}
};
vector <node > vct;
void Init()
{
	vct.clear();
	for(int i=0;i<=N;i++)
		for(int j=0;j<=M;j++)
		{
			str[i][j]='#';
			visit[i][j]=false;
		}
}
void DFS(int x,int y)
{
	if( x>=1 && x<=N && y>=1 && y<=M && str[x][y]=='0' && !visit[x][y])
	{
		vct.push_back(node(x,y));
		visit[x][y]=true;
		DFS(x,y+1);
		DFS(x,y-1);
		DFS(x+1,y);
		DFS(x-1,y);
	}
}

void solve()
{
	for(int i=0;i<=N;i++)
		for(int j=0;j<=M;j++)
			visit[i][j]=false;
	int Max=0;
	for(int i=0;i<vct.size();i++)
		if(vct[i].x+vct[i].y>Max)
			Max=vct[i].x+vct[i].y;

	for(int i=0;i<vct.size();i++)
		if(vct[i].x+vct[i].y==Max)
			visit[vct[i].x][vct[i].y]=true;

	int i,j,k,p,q;
	for(i=1;i<=N+M+1 && i+1<Max;i++) ;
	if(Max==0)
	{
		i=1;
		visit[1][1]=true;
	}

	for(;i<=N+M-1;i++)
	{
		if(i>=N+1)
		{
			j=N;
			k=i-N+1;
		}
		else
		{
			j=i;
			k=1;
		}
		bool fg=false;
		for(p=j,q=k;p>=1 && q<=M;p--,q++)
		{
			if(str[p][q]=='0' && visit[p][q])
			{
				fg=true;
				break;
			}
		}
		if(fg)
		{
			ans[len++]=0;
			for(p=j,q=k;p>=1 && q<=M;p--,q++)
			{
				if(str[p][q]=='0' && visit[p][q])
				{
					visit[p+1][q]=true;
					visit[p][q+1]=true;
				}
			}
		}
		else
		{
			ans[len++]=1;
			for(p=j,q=k;p>=1 && q<=M;p--,q++)
			{
				if(visit[p][q])
				{
					visit[p+1][q]=true;
					visit[p][q+1]=true;
				}
			}
		}
	}
}

int main()
{
	int ncase,i,j;
	scanf("%d",&ncase);
	while(ncase--)
	{
		scanf("%d%d",&N,&M);
		Init();
		for(i=1;i<=N;i++)
			scanf("%s",str[i]+1);
		DFS(1,1);
		len=0;
		solve();
		for(i=0;i<len && !ans[i] ;i++) ;
		if(i==len)
			printf("0\n");
		else
		{
			for(;i<len;i++)
				printf("%d",ans[i]);
			printf("\n");
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-22 16:44:35

hdu5335 Walk Out (递推||广搜)的相关文章

HDU--1142--A Walk Through the Forest--深广搜/DP/最短路径/记忆化搜索

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5948    Accepted Submission(s): 2191 Problem Description Jimmy experiences a lot of stress at work these days, especial

HDU5335 Walk Out(dfs+递推)

题意:大致意思是给一个n*m的01矩阵,起点为左上方(1,1),终点为右下方(n,m),求从左上方到右下方字典序自小的路径,如果路径都为0,则输出0. 分析:首先字典序最小,先要满足路径最短,再满足路径的值最小,路径最短的毫无疑问是越靠下或者越靠右,而且如果路径的前面为0,则可以认为是以第一个非0的点的为起点.因此这题可以转化为:先找出以起点为中心的连续为零的集合,再在其中找出x+y最大的一些点为起点,(当然如果s[1][1]==1,起点就是左上方),然后以这些点不断往下往右寻找下一排的最小值,

HDU - 6185 Covering(暴搜+递推+矩阵快速幂)

Covering Bob's school has a big playground, boys and girls always play games here after school. To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets. Meanwh

百练2755 神奇的口袋 【深搜】or【动规】or【普通递归】or【递推】

总Time Limit:  10000ms  Memory Limit:  65536kB 有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40.John现在有n个想要得到的物品,每个物品的体积分别是a1,a2--an.John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品.现在的问题是,John有多少种不同的选择物品的方式. Input 输入的第一行是正整数n (1 <= n <= 20),表示不

FOJ1205 小鼠迷宫问题 (BFD+递推)

FOJ1205 小鼠迷宫问题 (BFD+递推) 小鼠a与小鼠b身处一个m×n的迷宫中,如图所示.每一个方格表示迷宫中的一个房间.这m×n个房间中有一些房间是封闭的,不允许任何人进入.在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间.小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路.请帮助小鼠a找出所有通向小鼠b的最短道路. 图 小鼠的迷宫 编程任务: 对于给定的小鼠的迷宫,编程计算小鼠a通向小鼠b的所有最短道路.   INPUT: 由文件input.

解题报告 之 HDU5335 Walk Out

解题报告 之 HDU5335 Walk Out Description In an  maze, the right-bottom corner is the exit (position  is the exit). In every position of this maze, there is either a  or a  written on it. An explorer gets lost in this grid. His position now is , and he wan

NOIP 2002 马拦过河卒 BFS+递推

Description : 如图,A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右. 同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为方马的控制点.例如上图C点上的马可以控制9个点(图中的P1,P2...P8和C).卒不能通过对方的控制点. 棋盘用坐标表示,A点(0,0).B点(n, m)(n,m为不超过20的整数,并由键盘输入),同样马的位置坐标是需要给出的(约定:C≠A,同时C≠B).现在要求你计算出卒从A点能够到达B点的路 径的

hdu 2571 命运(递推,请小心)

题目 //不能广搜,会超内存//可以用dp思想模拟//map 后来保存的是 保存由前面推来的最大的幸运总值的点//下标从1开始,不然倍数会有问题 //AC 代码: AC代码 //不能广搜,会超内存 //可以用dp思想模拟 //map 后来保存的是 保存由前面推来的最大的幸运总值的点 //下标从1开始,不然倍数会有问题 //又错了那么多次... //重写... //求过!!! #include<stdio.h> #include<string.h> #include<algor

迷宫广搜

上学期学了C,这学期学C++.感觉最难的还是算法,上周作业的一道广搜题是我第一次接触广搜,由于第一学期刚学编程就接触的太多的算法难题,不禁对代码产生畏惧,不过还好没有放弃,虽然算法很难,但我慢慢找到了一点学数学时的乐趣.先介绍一下这道未来的我看过来会觉得很简单一道题吧 You are provided a maze(迷宫), and you need to program to find the least steps to walk from the start to the end.And