HDU 5335 多校第4场 1009 Walk Out

Walk Out

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

Total Submission(s): 1794    Accepted Submission(s): 340

Problem Description

In an n?m 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 (1≤n,m≤1000).
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

题意:

给你一个迷宫,迷宫由0 1串组成,让你从  1 1 点走到 n,m点 ,路径上的所以点连起来就是个二进制数,求这个二进制数的最小值

思路:

一个二进制数想要小,首先位数一定要小,其次每一位让0尽肯能的出现在前面,也会小,所以第一步找到距离终点最近的一个1,这个1满足起点到这个1直接只由0组成

找到这个1之后就可以贪心走又下方(不向左上的原因是会使位数变大),这里需要用生命来优化,走过的点不能走,不能让地图每个点都要个string 来标记这个点的值,这样都会爆内存。标记用一个string 来记录当前结果,用另一个变量标记这个数是搜索的第几层,总之用生命来优化,下面贴代码

/*********************************
** 2015 Multi-University Training Contest 4 1009
** 2015-7-31
** by calamity_coming
** hdu 5335
**********************************/

#include <bits/stdc++.h>
using namespace std;
const int inf=0x7f7f7f7f;
typedef unsigned int intt;
typedef long long ll;
const int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};

char maze[1010][1010];
int n,m;
struct Point
{
    int x,y;
    int fair()//到终点的距离
    {
        return m + n - x - y - 2;
    }
    Point (int _x = 0,int _y = 0) : x(_x) , y(_y) {}
};

class Solution
{
    bool end_zero;
    queue<Point> jb;
    int min_long;
    string final_ans;

public:
    Solution() : end_zero (false) , final_ans("1")
    {
        cin>>n>>m;
        for(int i=0; i<n; ++i)
        {
            cin>>maze[i];
        }
        if(maze[n-1][m-1] == '0')//让他为0好判断
        {
            end_zero = true;
            maze[n-1][m-1] = '1';
        }
        min_long = n+m-2;
    }

    /*********************************************************
    ** 寻找第一个1出现的位置
    ** 前提,已经把结尾强制设为1
    ************************************************************/
    void find_one()
    {
        if(maze[0][0] == '1')
        {
            jb.push(Point(0,0));
            return;
        }
        queue<Point> ac;
        ac.push(Point(0,0));
        while(!ac.empty())
        {
            Point adc = ac.front();
            ac.pop();
            for(int i=0; i<4; ++i)
            {
                int x = dir[i][0] + adc.x;
                int y = dir[i][1] + adc.y;
                if(x<0 || x>=n || y<0 || y>=m)
                    continue;
                if(maze[x][y] == '0')
                {
                    ac.push(Point(x,y));
                    maze[x][y] = '#';
                    continue;
                }
                if(maze[x][y] == '1')
                {
                    Point ap(x,y);
                    jb.push(ap);
                    maze[x][y] = '*';
                    if(ap.fair() < min_long)
                    {
                        min_long = ap.fair();
                        update_queue();//一定不为空
                    }
                }
            }
        }
    }

    void update_queue()//更新队列值,始终是满足最小的(用时间换空间)
    {
        for(int i=0,len = jb.size(); i<len; ++i)
        {
            Point adc = jb.front();
            jb.pop();
            if(min_long == adc.fair())
            {
                jb.push(adc);
            }
        }
    }

    /**********************************************************
    ** 广搜找到结果,只往右下方走
    ** 用生命在标记,防止爆内存
    ** 把走过的0变成#,1变成*,可以防止重复走
    *************************************************************/
    void bfs()
    {
        while(!jb.empty())
        {
            Point adc = jb.front();
            jb.pop();
            if(min_long == 0)
            {
                return ;
            }

            if(min_long == adc.fair() && maze[adc.x][adc.y] == '*' &&
                    final_ans[final_ans.size()-1] == '0') //被抛弃的点
            {
                continue;
            }

            if(adc.y + 1 < m)//向右
            {
                if(maze[adc.x][adc.y+1] == '0')
                {
                    Point ap = adc;
                    ap.y++;
                    if(min_long == ap.fair() + 1)//1 -> 10
                    {
                        min_long = ap.fair();
                        final_ans += '0';
                    }
                    else if(final_ans[final_ans.size()-1] == '1')//11 -> 10
                    {
                        final_ans[final_ans.size()-1] = '0';

                    }
                    jb.push(ap);
                    maze[adc.x][adc.y+1] = '#';
                }
                else if(maze[adc.x][adc.y + 1] == '1')
                {
                    if(adc.x + 1 >= n || (maze[adc.x+1][adc.y] != '0') && maze[adc.x+1][adc.y] != '#')
                    {
                        Point ap = adc;
                        ap.y++;
                        if(min_long == ap.fair() + 1)//111 -> 1111
                        {
                            min_long --;
                            final_ans += '1';
                            jb.push(ap);
                            maze[adc.x][adc.y+1] = '*';
                        }
                        else if(final_ans[final_ans.size()-1] == '1')// 11-> 11
                        {
                            jb.push(ap);
                            maze[adc.x][adc.y+1] = '*';
                        }
                    }
                }
            }

            if(adc.x + 1 < n)//向下
            {
                if(maze[adc.x+1][adc.y] == '0')
                {
                    Point ap = adc;
                    ap.x++;
                    if(min_long == ap.fair() + 1)//111 -> 1110
                    {
                        min_long = ap.fair();
                        final_ans += '0';
                    }
                    else if(final_ans[final_ans.size()-1] == '1')//1111 -> 1110
                    {
                        final_ans[final_ans.size()-1] = '0';
                    }
                    jb.push(ap);
                    maze[adc.x+1][adc.y] = '#';
                }

                else if(maze[adc.x+1][adc.y] == '1')
                {
                    if(adc.y + 1 >= m || (maze[adc.x][adc.y+1] != '0' && maze[adc.x][adc.y+1] != '#'))
                    {
                        Point ap = adc;
                        ap.x++;
                        if(min_long == ap.fair() +1)//111 -> 1111
                        {
                            min_long = ap.fair();
                            final_ans += '1';
                            jb.push(ap);
                            maze[adc.x+1][adc.y] = '*';
                        }

                        else if(final_ans[final_ans.size()-1] == '1')// 1111 -> 1111
                        {
                            jb.push(ap);
                            maze[adc.x+1][adc.y] = '*';
                        }
                    }
                }
            }
        }
    }

    void Win_S5()
    {
        find_one();
        update_queue();//最后一定要再次更新一下,删除不该有的东西
        bfs();
        if(end_zero)
        {
            final_ans[final_ans.size()-1] = '0';
        }
        cout<<final_ans<<endl;
    }
};
int main()
{
    ios::sync_with_stdio(false);
    int t;
    int cot = 0;
    cin>>t;
    while(t--)
    {
        Solution OMG;
        OMG.Win_S5();
    }
    return 0;
}

挺虐心的,200多行,WA了一天,最后发现是队列少更新一次,还是不够细心啊

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

时间: 2024-08-30 07:31:11

HDU 5335 多校第4场 1009 Walk Out的相关文章

HDU 4869 Turn the pokers 多校训练第一场1009

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 282    Accepted Submission(s): 89 Problem Description During summer vacation,Alice stay at home for a long time, with nothing to

HDU 5358 多校第6场 First One

First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 672    Accepted Submission(s): 193 Problem Description soda has an integer array . Let  be the sum of . Now soda wants to know the va

hdu 5317 多校第三场

开始题意读错了   shit    wa了好久    仔细一看真是水题一枚: 根据素数打表很容易得出每个数的F()值     从而可以看出1到1000000  F()的值最大为7  及(2*3*5*7*11*13*17)   告诉你区间    只需要在这个区间里找到这7个数分辨出先了多少次  这里用一个二维的数组leap[i][j](j小于等于7) 表示i之前j出现的次数    这样就很容易求出区间j的值    纪录在record数组里    就可以求GCD了  这里 我是直接把所有情况列出来了

hdu 2018 多校 第五场

1002 小洛洛 开场挂了N发插入排序的我( 最后还是要靠小洛洛写暴力 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 #include <cstdlib> 6 #include <algorithm> 7 using namespace std; 8 9 const int N = 12; 10 11 int mi

HDU暑假多校第八场J-Taotao Picks Apples

一.题意 给定一个序列,之后给出若干个修改,修改的内容为在原序列的基础上,将某一位元素的值改成给定的值<每次修改相互独立,不保存修改后的结果>.之后询问,在选择第一位元素的情况下,最长递增子序列的长度是多少. 二.题解 考虑不经修改的情况,应当设dp[i]为选取当前位情况下的最长递增子串的长度.则对于这道题,应当认为对于修改a为b,设l_pos为a左边最大的元素的位置,r_pos为a右边大于max(b,r_pos)的元素的位置.则有ans = dp[1] - dp[l_pos] + 1 + d

2019HDU多校第六场1009 Three Investigators——杨表

题意 给定一个 n 个元素的数列,从前 k 个元素中取5次不下降子序列,求取得的和的最大值(k从1至n) 分析 考虑将数字 a[i] 拆成 a[i] 个 a[i],比如 “4,1,2”→“4,4,4,4,1,2,2”,则问题转化为:找到最多 5 个不共享元素的不下降子序列,使得这些子序列包含的元素总量最多.可以证明,这等于杨氏图表前 5 层的长度之和.(手动模拟一下就能发现) 考虑杨氏图表求解答案的过程: 从 1 到 n 依次考虑序列中的每个数,将其插入杨氏图表的第一层中. 插入 x 时,如果

HDU 4968 Improving the GPA 多校第九场1009

Problem Description Xueba: Using the 4-Point Scale, my GPA is 4.0. In fact, the AVERAGE SCORE of Xueba is calculated by the following formula: AVERAGE SCORE = ∑(Wi * SCOREi) / ∑(Wi) 1<=i<=N where SCOREi represents the scores of the ith course and Wi

hdu5335 多校联合第四场1009 搜索

http://acm.hdu.edu.cn/showproblem.php?pid=5335 Problem Description In an n?m 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 th

2014多校第十场1004 || HDU 4974 A simple water problem

题目链接 题意 : n支队伍,每场两个队伍表演,有可能两个队伍都得一分,也可能其中一个队伍一分,也可能都是0分,每个队伍将参加的场次得到的分数加起来,给你每个队伍最终得分,让你计算至少表演了几场. 思路 : ans = max(maxx,(sum+1)/2) :其实想想就可以,如果所有得分中最大值没有和的一半大,那就是队伍中一半一半对打,否则的话最大的那个就都包了. 1 #include <cstdio> 2 #include <cstring> 3 #include <st