hdoj 1983 Kaitou Kid - The Phantom Thief (2) (dfs+bfs)

5 篇文章 0 订阅
5 篇文章 0 订阅

【题目大意】:你得知Kid将会在展览开始后T分钟内盗取至少一颗宝石,并离开展馆。整个展馆呈矩形分布,划分为N*M个区域,有唯一的入口和出口(不能从出口进入,同样不能从入口出去)。由某个区域可直接移动至相邻四个区域中的一个,且最快需要一分钟。假设Kid进入放有宝石的区域即可盗取宝石,无需耗时。问至少要封锁几个区域(可以封锁放有宝石的区域,但不能封锁入口和出口)才能保证Kid无法完成任务。


【解题思路】:其实读完题目我们显然可以发现,在最坏的情况下我只需要将出口和入口附近非“#”的区域封闭即刻。换句话说,最坏的情况不会超过封锁4块区域。

因此,我们不妨考虑先根据出入口和在不封锁区域的情况下是否存在可行路径来得到当前所需封锁区域的最小值。

之后,我们通过dfs来枚举小于当前最小区域封锁值时的点,再通过bfs求最短路验证即刻。

坑爹的事...下午贡献了无限次wa。。。现实把p.x敲成p,x之后发现去min的时候居然忘了写min函数....==....真应该剖腹以谢天下!!!


【代码】:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
                   
using namespace std;
                   
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long

int tx[4]={-1,1,0,0};
int ty[4]={0,0,-1,1};
int x,y,minn,t,xx,yy,n,m;
int vis[10][10][2];
char ch[10][10];
bool flag1;
char tmp[5];

struct Node{
    int x,y,cnt,flag;
    Node() {}
    Node(int a,int b,int c,int d){
        x=a,y=b,cnt=c,flag=d;
    }
};

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

bool solve_bfs(){
    queue<Node> que;
    que.push(Node(x,y,0,0));
    memset(vis,0,sizeof(vis));
    vis[x][y][0]=1;
    while (!que.empty()){
        Node q;
        q=que.front();
        que.pop();
        for (int i=0; i<4; i++){
            Node p;
            p.x=q.x+tx[i];
            p.y=q.y+ty[i];
            p.cnt=q.cnt+1;
            p.flag=q.flag;
            if (check(p.x,p.y) && ch[p.x][p.y]!='#'){
                if (ch[p.x][p.y]=='E' && p.flag==1) return true;
                if (ch[p.x][p.y]=='J') p.flag=1;
                if (p.cnt<t && vis[p.x][p.y][p.flag]==0){
                    vis[p.x][p.y][p.flag]=1;
                    que.push(p);
                } 
            }
        }
    }
    return false;    
}

int solve_min(){
    int nx,ny,min1=0,min2=0;
    for (int i=0; i<4; i++){
        nx=x+tx[i];
        ny=y+ty[i];
        if (check(nx,ny) && (ch[nx][ny]=='.' || ch[nx][ny]=='J'))
           min1++; 
    }
    for (int i=0; i<4; i++){
        nx=xx+tx[i];
        ny=yy+ty[i];
        if (check(nx,ny) && (ch[nx][ny]=='.' || ch[nx][ny]=='J'))
           min2++; 
    }
    return min(min1,min2);
}

void solve_dfs(int count,int now){
    if (count<minn){
        for (int i=0; i<n; i++)
            for (int j=0; j<m; j++){                
                if (ch[i][j]=='.' || ch[i][j]=='J'){
                    tmp[now]=ch[i][j];
                    ch[i][j]='#';
                    if (now==count) if (!solve_bfs()) {minn=min(count,minn); flag1=true; return ;}
                    if (flag1) return ;
                    if (now<count) solve_dfs(count,now+1);
                    ch[i][j]=tmp[now];                    
                }
            }
    }
    else return ;
}

int main() {
    int T;
    scanf("%d",&T);
    while (T--){
        scanf("%d%d%d",&n,&m,&t);
        getchar();
        for (int i=0; i<n; i++){
            for (int j=0; j<m; j++){
                scanf("%c",&ch[i][j]);
                if (ch[i][j]=='S') x=i,y=j;
                if (ch[i][j]=='E') xx=i,yy=j;
            }
            getchar();
        }
        minn=solve_min();
        if (!solve_bfs()) minn=0;
        flag1=false;
        solve_dfs(1,1);
        flag1=false;
        solve_dfs(2,1);
        flag1=false;
        solve_dfs(3,1);
        printf("%d\n",minn);  
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值