码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5335(2015 ACM多校训练第四场1009)

时间:2015-08-01 17:24:04      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:icpc   acm   acm-icpc   贪心   iostream   

Walk Out

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2469    Accepted Submission(s): 485


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 (1n,m1000). The i-th line of the next n lines contains one 01 string of length m, which representsi-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
 

题意:
给一个n*m的图。图上每个位置为0或者1。
有一个人在该图中走。每走一个位置把该位置的数字记录下来。
问从这个人从图的左上角(0,0)走到图的右下角(n-1,m-1)形成的二进制数最小是多少,输出这个二进制(该二进制的前导0不必输出)。

思路:
初次看本题时以为是一个从左上角向右下角的dp,但是仔细想想就会有问题,dp的状态转移情况不一定是向右或者是向下的。
例如:

5 5
01111
01000
01010
01010
00011

答案是:1

后来想想应该是一个向下或向右的贪心。但是这样还是无法处理上述的情况,最后只能对这种情况进行特殊处理;
当起始点为0时先把所有与起始点相邻的0点跑出来,放进优先队列里面,然后取其中横坐标+纵坐标最大的值(横坐标+纵坐标越大,离(n-1,m-1)的距离越近,二进制位数越小,二进制值越小),当然如果这样的值有多个则都取出来,每个都进行向下向右的BFS广搜,而且广搜的同时,再与终点距离相同的点中,优先选择所有的0点,一旦存在0点则放弃所有1点。

至于这些如何实现。。。。。。。。。。。。。。不得不承认自己还是太弱了。竟然需要用两个优先队列,两个普通队列来实现。
后来看了别人短小精悍的代码后更是感觉自己的代码无法直视O__O "…
虽然这样写起来思路非常清晰,但是代码还是太冗长了 (>﹏<)


#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int maxx = 1000 + 10;
int n, m;
char str[maxx][maxx];
char ans[maxx*maxx];
char ans_str[maxx*maxx];
bool vis[maxx][maxx];
int kjudge;

int dir1[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
struct node1{
    int x;
    int y;
    bool operator < (const node1 & a)const{
        return a.x+a.y > x+y;
    }
};
priority_queue<node1> pp1;
queue<node1> p1;

int dir2[2][2] = {{1,0},{0,1}};
struct node2{
    int x;
    int y;
    int num;
    int id;
    bool operator < (const node2& a) const {
        if(a.num == num) return a.id < id;
        return a.num < num;
    }
};
priority_queue<node2> pp2;
queue<node2> p2;

bool ok(int x,int y){
    if(x<0||x>=n)
        return false;
    if(y<0||y>=m)
        return false;
    return true;
}

bool ok1(int x,int y){
    if(ok(x,y)&&str[x][y] == '0'){
        return true;
    }
    return false;
}

bool ok2(int x,int y){
    if(ok(x,y)&&vis[x][y] == false){
        return true;
    }
    return false;
}

void output(int len){
    int i = 0;
    if(ans_str[0] == '9') i++;
    for(; i < len; ++i){
        printf("%c",ans_str[i]);
    }
    printf("\n");
}

int bfs2(int x,int y){
    node2 k;
    if(str[n-1][m-1] == '9'){
        printf("0\n");
        return -1;
    }
    if(x == n-1 &&y == m-1){
        printf("%c\n",str[n-1][m-1]);
        return -1;
    }
    memset(vis,false,sizeof(vis));
    memset(ans,'_',sizeof(ans));
    k.x = x;
    k.y = y;
    k.num = 1;
    ans[0] = str[k.x][k.y];
    k.id = str[k.x][k.y] - '0';
    vis[x][y] = true;
    pp2.push(k);
    int now = k.num;
    int judge = k.id;
    while(!pp2.empty()){
        node2 q = pp2.top();
        pp2.pop();
        if(now != q.num){
            now = q.num;
            judge = q.id;
        }
        if(judge == q.id){
            for(int i = 0;i < 2; ++i){
                int dx = dir2[i][0]+q.x;
                int dy = dir2[i][1]+q.y;
                if(dx == n-1 && dy == m-1){
                    ans[q.num] = str[dx][dy];
                    if(!kjudge){
                        for(int j = 0;j <= q.num; ++j){
                            ans_str[j] = ans[j];
                        }
                    }else{
                        int mj = 0;
                        for(int j = 0;j <= q.num; ++j){
                            if(ans_str[j] > ans[j]){
                                mj = 1;
                                break;
                            }
                        }
                        if(mj){
                            for(int j = 0;j <= q.num; ++j){
                                ans_str[j] = ans[j];
                            }
                        }
                    }
                    while(!pp2.empty()) pp2.pop();
                    return q.num+1;
                }
                if(ok2(dx,dy)){
                    if(ans[q.num] == '_')ans[q.num] = str[dx][dy];
                    else ans[q.num] = min(ans[q.num],str[dx][dy]);
                    vis[dx][dy] = true;
                    node2 temp;
                    temp.id = str[dx][dy] - '0';
                    temp.x = dx;
                    temp.y = dy;
                    temp.num = q.num+1;
                    pp2.push(temp);
                }
            }
        }
    }
}

void bfs1(){ ///找起点位置
    node1 k;
    k.x = 0;
    k.y = 0;
    kjudge = 0;
    int klen = -1;
    if(str[0][0] == '0') {
        p1.push(k);
        str[0][0] = '9';
        while(!p1.empty()){
            node1 q = p1.front();
            pp1.push(q);
            p1.pop();
            for(int i = 0;i < 4; ++i){
                int dx = dir1[i][0] + q.x;
                int dy = dir1[i][1] + q.y;
                if(ok1(dx,dy)){
                    node1 temp;
                    temp.x = dx;
                    temp.y = dy;
                    str[dx][dy] = '9';
                    p1.push(temp);
                }
            }
        }
        int judge  = pp1.top().x + pp1.top().y;
        while(!pp1.empty()){
            node1 temp = pp1.top();
            if(judge == temp.x+temp.y){
                klen = bfs2(temp.x,temp.y);
            }
            pp1.pop();
        }
    }else{
        klen = bfs2(0,0);
    }
    if(klen != -1)output(klen);
}

int main(){
    int T;
    cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i = 0;i < n; ++i){
            scanf("%s",str[i]);
        }
        bfs1();
    }
    return 0;
}

如有BUG,请大家务必指出,不胜感激~

联系方式:274489985@qq.com

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

HDU 5335(2015 ACM多校训练第四场1009)

标签:icpc   acm   acm-icpc   贪心   iostream   

原文地址:http://blog.csdn.net/u012844301/article/details/47186949

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!