HDU 5335 Walk Out

本文探讨了在一个由字符 '0' 和 '1' 组成的 n*m 迷宫中,从左上角出发到达右下角的最短路径。通过广搜算法寻找离终点最近的点,并采用贪心策略,确保路径上的数字以尽可能少的 '1' 开始,从而得到最小的二进制表示。特别关注于如何在有限的步骤内优化路径选择,以获得最优的二进制编码结果。

Walk Out

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)


Problem Description
In an  nm  maze, the right-bottom corner is the exit (position  (n,m)  is the exit). In every position of this maze, there is either a  0  or a  1  written on it.

An explorer gets lost in this grid. His position now is  (1,1) , and he wants to go to the exit. Since to arrive at the exit is easy for him, he wants to do something more difficult. At first, he'll write down the number on position  (1,1) . Every time, he could make a move to one adjacent position (two positions are adjacent if and only if they share an edge). While walking, he will write down the number on the position he's on to the end of his number. When finished, he will get a binary number. Please determine the minimum value of this number in binary system.
 

Input
The first line of the input is a single integer  T (T=10) , indicating the number of testcases. 

For each testcase, the first line contains two integers  n  and  m (1n,m1000) . The  i -th line of the next  n  lines contains one 01 string of length  m , which represents  i -th row of the maze.
 

Output
For each testcase, print the answer in binary system. Please eliminate all the preceding  0  unless the answer itself is  0  (in this case, print  0  instead).
 

Sample Input
  
2 2 2 11 11 3 3 001 111 101
 

Sample Output
  
111 101
 

Author
XJZX
 

Source

/*************************************************************/

题意:一个由字符'0'、'1'组成的n*m的迷宫,起点在左上角(1,1),终点在右下角(n,m),每次探险者可以往上下左右四个方向移动,并且记下当前位置的字符。到达终点后,他会得到一个二进制数(即探险者记录下来的字符串),要求探险者如何走能得到最小的二进制数,输出该二进制数(不含前导0,若字符串每个字符都为'0',则输出'0')。


解题思路:
      广搜(BFS)+贪心,要使得到的二进制数最小,而且不包括前导0,那么我们很容易就可以想到遇到1之前都走0,走到距离终点最近的位置(即与终点曼哈顿距离最小的点,亦或者说x+y(x,y为当前位置的坐标)尽可能大的点)使得后面的路径尽可能短。
①先是bfs找到离目标最近的距离;
②后用贪心的思想让靠前的字符尽可能为0。
策略是每往前走一步,判断是否 可以是0,有0就走0,没0才走1,直到终点。

给几组测试数据

100
5 5
01101
00011
01111
11111
11110


100
1 1
1


100

1 1

0


100
5 5
10011
11010
00111
11111
00010


100
5 5
00011
11011
10011
11011
00001


闲话不多说,上AC代码,用时140Ms

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 1005;
const int inf = 1000000000;
char s[N][N];
bool v[N][N];
int g[4][2]={{0,1},{1,0},{0,-1},{-1,0}},n,m,a,b;
struct node
{
    int x,y;
    node(){}
    node(int x1,int y1):x(x1),y(y1){}
};
void BFS(int x,int y)
{
    memset(v,false,sizeof(v));
    v[x][y]=true;
    if(s[x][y]=='1')
    {
        a=b=1;
        return ;
    }
    int i,Max=0;
    queue<node> q;
    q.push(node(x,y));
    while(!q.empty())
    {
        for(i=0;i<4;i++)
        {
            x=q.front().x+g[i][0];
            y=q.front().y+g[i][1];
            if(!v[x][y]&&x>0&&y>0&&x<=n&&y<=m&&s[x][y]=='0')
            {
                v[x][y]=true;
                q.push(node(x,y));
            }
        }
        if(q.front().x+q.front().y>Max)
            a=q.front().x,b=q.front().y,Max=q.front().x+q.front().y;
        q.pop();
    }
}
int main()
{
	int t,i,j,k,l,x,y;
	bool flag;
	scanf("%d",&t);
	while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        BFS(1,1);
        if(n+m==2)
        {
            printf("%c\n",s[1][1]);
            continue;
        }
        else if(a+b==n+m)
        {
            puts("0");
            continue;
        }
       // printf("%d %d\n",a,b);
        if(a+b==2)
            printf("1");
        for(i=a+b;i<n+m;i++)
        {
            for(j=1;j<=n;j++)
            {
                k=i-j;
                flag=false;
                if(k>0&&v[j][k])
                {
                    for(l=0;l<2;l++)
                    {
                        x=j+g[l][0];
                        y=k+g[l][1];
                        if(x>0&&y>0&&x<=n&&y<=m&&s[x][y]=='0')
                            flag=true;
                    }
                }
                if(flag)
                    break;
            }
            if(flag)
                printf("0");
            else
                printf("1");
            for(j=1;j<=n;j++)
            {
                k=i-j;
                if(k>0&&v[j][k])
                {
                    for(l=0;l<2;l++)
                    {
                        x=j+g[l][0];
                        y=k+g[l][1];
                        if(x>0&&y>0&&x<=n&&y<=m&&(flag&&s[x][y]=='0'||!flag))
                            v[x][y]=true;
                    }
                }
            }
        }
        puts("");
    }
	return 0;
}

菜鸟成长记

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值