zoukankan      html  css  js  c++  java
  • HDU 5652 India and China Origins 二分优化+BFS剪枝

    题目大意:给你一个地图0代表可以通过1代表不可以通过。只要能从第一行走到最后一行,那么中国与印度是可以联通的。现在给你q个点,每年风沙会按顺序侵蚀这个点,使改点不可通过。问几年后中国与印度不连通。若一直联通输出-1.

    题目思路:看数据这道题就是卡时间的,我们的基本思路是每当风沙侵蚀一个点,我们就进行一次广搜,看看图上下是否联通,我们应尽可能的去优化这个过程。

    所以我们可以在遍历年的时候用二分查找:

    若当年图可以上下联通,则继续向右查找

    若当年图上下无法联通,则向左查找

    剪枝:

    为了省时间我们应该剪去一些不必要走的路径:假设第一行的x点在第n年已经不可达到最后一行,那么我们就标记一下,在m(m>n)年时,不对x点经行广搜。

    具体看代码:

    #include<cstdio>
    #include<stdio.h>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define INF 0x3f3f3f3f
    #define MAX 1000005
    #define mod 1000000007
    
    using namespace std;
    struct node
    {
        int x,y;
    };
    char Map[505][505];
    int vis[505][505],n,m,q,a[MAX],b[MAX],book[MAX],v[4][2]= {{1,0},{-1,0},{0,1},{0,-1}},Stack[MAX];
    
    int check(int x,int y)
    {
        if(x>=0 && x<n && y>=0 && y<m && !vis[x][y] && Map[x][y]=='0')
            return 1;
        return 0;
    }
    
    int BFS(int x,int y)
    {
        vis[x][y]=1;
        node now,next;
        now.x=x;
        now.y=y;
        queue<node>Q;
        Q.push(now);
        while(!Q.empty())
        {
            now=Q.front();
            Q.pop();
            if(now.x==n-1)
            {
                return 1;
            }
            for(int i=0; i<4; i++)
            {
                next.x=now.x+v[i][0];
                next.y=now.y+v[i][1];
                if(check(next.x,next.y))
                {
                    vis[next.x][next.y]=1;
                    Q.push(next);
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        int T,i,j,ans,ok1,ok2,ok,L,R,top;
        scanf("%d",&T);
        while(T--)
        {
            ok1=0;//记录第一行是否有可行点
            ok2=0;//记录第二行是否有可行点
            ok=0;
            scanf("%d%d",&n,&m);
            for(i=0; i<n; i++)
                scanf("%s",Map[i]);
            scanf("%d",&q);
            for(i=1; i<=q; i++)
                scanf("%d%d",&a[i],&b[i]);
            for(i=0; i<m; i++)
            {
                if(Map[0][i]=='0')
                    ok1=1;
                if(Map[n-1][i]=='0')
                    ok2=1;
            }
            if(ok1 && ok2)
                ok=1;
            if(!ok)//若第一行或最后一行无可行点,直接输出0
            {
                printf("0
    ");
                continue;
            }
            ans=0;
            L=1;
            R=q;
            memset(book,0,sizeof(book));//记录第一行被剪去的点
            while(R>L)//二分查找年份
            {
                top=0;
                int mid=L+(R-L)/2;
                for(i=1; i<=mid; i++)//当前为mid年,更新地图被侵蚀的点
                {
                    int x=a[i];
                    int y=b[i];
                    Map[x][y]='1';
                }
                ok=0;
                for(i=0; i<m; i++)
                {
                    if(Map[0][i]=='0' && !book[i])
                    {
                        memset(vis,0,sizeof(vis));
                        ok=BFS(0,i);
                        if(ok)//当年图上下可连通
                            break;
                        else
                        {
                            Stack[++top]=i;//若该点无法到达最后一行,记录改点为可能要被剪去的点
                        }
                    }
                }
    
                if(ok)
                {
                    L=mid+1;
                    ans=max(ans,mid);
                    for(j=1; j<=top; j++)//剪枝
                    {
                        int num=Stack[j];
                        book[num]=1;
                    }
                    top=0;
                }
                else
                {
                    R=mid;
                }
    
                for(i=1; i<=mid; i++)//还原地图
                {
                    int x=a[i];
                    int y=b[i];
                    Map[x][y]='0';
                }
            }
    
            ok=0;
            for(i=1; i<=L; i++)
            {
                int x=a[i];
                int y=b[i];
                Map[x][y]='1';
            }
            for(i=0; i<m; i++)
            {
                if(Map[0][i]=='0' && !book[i])
                {
                    memset(vis,0,sizeof(vis));
                    ok=BFS(0,i);
                    if(ok)
                        break;
                    else
                    {
                        Stack[++top]=i;
                    }
                }
            }
            if(ok)
                ans=L;
                
            if(ans == q)
                ans=-1;
            else
                ans++;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    maven mirror
    cas sso单点登录系列8_抛弃Https让Cas以Http协议提供单点登录服务
    cas sso单点登录系列7_ 单点登录cas常见问题系列汇总
    cas sso单点登录系列6_cas单点登录防止登出退出后刷新后退ticket失效报500错
    cas sso单点登录系列5_cas单点登录增加验证码功能完整步骤
    cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)
    cas sso单点登录系列3_cas-server端配置认证方式实践(数据源+自定义java类认证)
    cas sso单点登录系列2:cas客户端和cas服务端交互原理动画图解,cas协议终极分析
    cas sso单点登录系列1_cas-client Filter源码解码(转)
    Mysql事务机制
  • 原文地址:https://www.cnblogs.com/alan-W/p/5785244.html
Copyright © 2011-2022 走看看