hdu 5334 多校(4)

题意是给你一个n*m的有0 1组成的矩阵    起点为坐上角  终点为右下角  从起点走到终点组成的一个二进制数最小;

思路:

1. 如果起点为零   则找到与起点相邻的联通0  的点 找到距离终点最近的一些点    然后找到最小的二进制数(建议用 bfs)

2.起点不为0  则直接从起点开始找最小的二进制数  具体找法为:

把下一步的点走找出来   如果其中有0的点 则不用走位1的点 把为零的加入队列 如果没有  则把所有的都加入队列   走的时候只用走右边和下边   想想为什么(2^ n肯定大于  2^(n-1)+.....2^0   说明长度越短越小)注意走过的点不能再走了(RE了好久) 具体实现我是用了一个优先队列(找到距离最小且为0 的起点) 一个普通队列  在跑起点时候 和对每个起点找到最小路径的时候。。。。。


#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;

char map[2100][2100];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int mark[2010][2010];
int n,m;
int path[3100];
struct node
{
    int x,y;
}a,b;
struct Node
{
    int x,y,dis;
    bool operator < (const Node& g) const
    {
        return dis>g.dis;
    }
}a1,b1;
priority_queue<Node>Q;
int bfs1(int x,int y)//找到所有起点
{
    int flash=0;
    a.x=x;
    a.y=y;
    a1.x=x;
    a1.y=y;
    a1.dis=n-x+m-y-1;
    
    Q.push(a1);
    queue<node>q;
    memset(mark,0,sizeof(mark));
    if(map[a.x][a.y]=='0') q.push(a); 
    mark[a.x][a.y]=1;
    while(!q.empty())
    {
        b=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            a.x=b.x+dir[i][0];
            a.y=b.y+dir[i][1];
            if(a.x<0||a.x>=n||a.y<0||a.y>=m) continue;
            if(mark[a.x][a.y]==0&&map[a.x][a.y]=='0')
            {
                mark[a.x][a.y]=1;
                q.push(a);
                if(a.x==n-1&&a.y==m-1) flash=1;
                a1.x=a.x;
                a1.y=a.y;
                a1.dis=n+m-a.x-a.y-1;
                Q.push(a1);
            }
        }
    }
    if(flash) return 1;
    return 0;    
}
int bfs2(int x,int y,int dis)//对每个起点  找到最小路径
{
    int route[3100];
    int leap[3100][3];
    memset(mark,0,sizeof(mark));//开始少了这个标记走过的  re了好久
    queue<node>qq;
    a.x=x;
    a.y=y;
    qq.push(a);
    int flash,j=0;
    route[++j]=map[a.x][a.y]-'0';
    int k;
    while(1)//对每层的情况
    {
        k=0;
        flash=0;
        while(!qq.empty())
        {
            b=qq.front();
            qq.pop();
            
            if(b.x+1<n&&mark[b.x+1][b.y]==0)
            {
                mark[b.x+1][b.y]=1;
                leap[++k][1]=b.x+1;
                leap[k][2]=b.y;
                if(map[b.x+1][b.y]=='0') flash=1;
            }
            if(b.y+1<m&&mark[b.x][b.y+1]==0)
            {
                mark[b.x][b.y+1]=1;
                leap[++k][1]=b.x;
                leap[k][2]=b.y+1;
                if(map[b.x][b.y+1]=='0') flash=1;
            }
        }
        if(k==0) break;
        if(flash) route[++j]=0;
        else route[++j]=1;
        for(int i=1;i<=k;i++)
        {    
            a.x=leap[i][1];
            a.y=leap[i][2];
            if(flash==0)
            {
                qq.push(a);
            }
            else 
            {
                if(map[a.x][a.y]=='0') qq.push(a);
            }
        }
    }
    flash=0;
    for(int i=1;i<=j;i++)
    {
        if(flash) path[i]=route[i];
        else 
        {
            if(route[i]<path[i]) 
            {
                path[i]=route[i];
                flash=1;
            }
        }
    }
    return 0;
}
int main()
{
    int T,i,j;                         
    scanf("%d",&T);                    
    while(T--)                         
    {                                  
        scanf("%d%d",&n,&m);              
        for(i=0;i<n;i++)                  
        scanf("%s",map[i]); 
        if(n==1&&m==1) {printf("%c\n",map[0][0]);continue;}
        
        while(!Q.empty())
        {
            a1=Q.top();
            Q.pop();
        }  
                    
        int d=bfs1(0,0);                    
        if(d==1) {printf("0\n");continue;} 
        for(i=0;i<=2010;i++)               
        path[i]=1;                         
                                       
        b1=Q.top();                    
        Q.pop();                           
        int Min=b1.dis;                     
        bfs2(b1.x,b1.y,b1.dis);               
                                       
        while(!Q.empty())                  
        {                                  
            b1=Q.top();                       
            Q.pop();                          
            if(b1.dis>Min) break;             
            bfs2(b1.x,b1.y,b1.dis);           
        }                                  
        if(path[1]==0) i=2;                
        else i=1;                          
        for(;i<=Min;i++)                 
        printf("%d",path[i]);              
        printf("\n");                      
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值