zoukankan      html  css  js  c++  java
  • hdu 1983 Kaitou Kid The Phantom Thief (2) DFS + BFS

    http://acm.hdu.edu.cn/showproblem.php?pid=1983

    转自:http://hi.baidu.com/song19870626/blog/item/b44a8110d9341376ca80c48d.html

    思路:

    封锁出口或者入口周围的格子.

    最多需要4个封锁点.

    所以我们可以采取这样的策略:

    1.寻找一条盗贼的可行路线,如果没有,返回0.

    2.计算封锁出口和入口四周需要的封锁点数量,取小的一个,假设是k,k <=4

    3.从少到多,遍历所有封锁点个数小于k的方案,验证是否是一条有效的覆盖方案

    (可以通过是否阻止了1中的盗贼线路进行快速验证).

    如果有有效覆盖方案,返回这个方案的覆盖点值,否则继续.

    4.如果没有比k小的覆盖方案,返回k.

    时间复杂度:

    最多(M*N)^3次有效覆盖验证.即(8*8)^3=256k次.其中有很大一部分可以通过快速验证排除(取决于1的路径长短,所以一般1应该求出最短路径的可行路线)

    #include <iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include <queue>
    #include <string>
    using namespace std;
    int n,m,t,ans;
    int dir[4][2] = {1,0,-1,0,0,-1,0,1};
    char map[10][10];
    bool vis[2][10][10];
    struct node
    {
        int x,y,t,k;
        int rox[64],roy[64];
    };
    node start,end,temp,in;
    queue <node> Q;
    void dfs(int deep)
    {
        if(deep > ans) return ;
        int i,j,minstep = -1;
        node q;
        while(!Q.empty())//清空队列
        Q.pop();
        Q.push(start);//起始位置入队
        memset(vis,false,sizeof(vis));//初始化标记数组
        vis[0][start.x][start.y] = true;//标记起始点为真
        while(!Q.empty())//从起点开始寻找一条路径
        {
            q = Q.front();
            Q.pop();
            if(q.t > t)
            break;
            if(q.k && map[q.x][q.y] == 'E')//找到出口
            {
                minstep = q.t;
                break;
            }
            for(i = 0;i < 4;i++)//分别从四个方向开始扫描
            {
                int xx = q.x + dir[i][0];
                int yy = q.y + dir[i][1];
                if(xx < 0 || xx >= n || yy < 0 || yy >= m || map[xx][yy] == '#')
                continue;//越界或碰到墙
                if(map[xx][yy] == 'J')
                in.k = 1;//碰到珠宝
                else
                in.k = q.k;//没有碰到则标记为前一个状态
                if(!vis[in.k][xx][yy])
                {
                    vis[in.k][xx][yy] = true;
                    for(j = 1;j <= q.t;j++)
                    {
                        in.rox[j] = q.rox[j];
                        in.roy[j] = q.roy[j];
                    }
                    in.x = xx;
                    in.y = yy;
                    in.t = q.t + 1;
                    in.rox[in.t] = xx;
                    in.roy[in.t] = yy;
                    Q.push(in);
                }
            }
        }
        if(minstep == -1)
        {// minstep == -1 表明在t时间内即使不用设置关卡也不能成功逃离
            if(deep < ans)
            ans = deep;
            return ;
        }
        char cc;
        for(i = 1;i < q.t;i++)
        {
            cc = map[q.rox[i]][q.roy[i]];
            if(cc == 'S' || cc == 'E')
            continue;
            map[q.rox[i]][q.roy[i]] = '#';
            dfs(deep+1);
            map[q.rox[i]][q.roy[i]] = cc ;
        }
    }
    void inits()
    {
        int i,j;
        memset(vis,false,sizeof(vis));
        for(i = 0;i < n;i++)
        for(j = 0;j < m;j++)
        {
            if(map[i][j] == 'S')
            {
                start.x = i;start.y = j;
                start.t = 0;start.k = 0;
                break;
            }
        }
        ans = 4;
        dfs(0);
        printf("%d\n",ans);
    }
    int main()
    {
        int i,cas;
        scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d%d%d",&n,&m,&t);
            for(i = 0;i < n;i++)
            scanf("%s",map[i]);
        inits();
        }
        return 0;
    }

     

  • 相关阅读:
    批量刷新远程物化视图的方法(备用)
    Oracle 11g中CTE应用示例
    PL/SQL DEVELOPER中查询结果复制出来中文乱码的解决方案
    RHEL5.5 64位下安装Oracle 11g 64位安装前置条件的两种方法
    不良言论屏蔽方案探讨——自说自话方案
    AWWWB 网站克隆器 v2.0发布
    OneNote中到底能放多少种东西?
    Visual Studio 2010 旗舰版 安装问题小记
    WPF命中测试示例(一)——坐标点命中测试
    网页内嵌Windows Media Player播放器的多文件播放方法
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740247.html
Copyright © 2011-2022 走看看