hdu 1983 Kaitou Kid - The Phantom Thief (2)【Bfs+暴力枚举】

Kaitou Kid - The Phantom Thief (2)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1268    Accepted Submission(s): 454

Problem Description

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

 

 

Input

输入的第一行有一个整数C,代表有C组测试数据。每组测试数据的第一行有三个整数NMT(2<=N,M<=8,T>0)。接下来NM列为展馆布置图,其中包括:

'S':入口
'E':出口
'J':放有宝石的区域,至少出现一次
'.':空白区域
'#':墙

 

 

Output

对每组测试数据,输出至少要封锁的区域数。

 

 

Sample Input

2

5 5 5

SJJJJ

..##J

.JJJJ

.J...

EJ...

5 5 6

SJJJJ

..##J

.JJJJ

.J...

EJ...

 

 

Sample Output

0

2

 

 

Author

LL

 

 

Source

2008杭电集训队选拔赛

 

其实这个题应该是保证了没有SE紧挨的情况。一会对应我的思路大家就能知道为什么。

 对于这个题后台数据的异议,这种样例应该输出3呢,还是6呢。。。。不过没有卵子关系,这个题的后台数据应该保证了没有SE紧挨的情况,应该也没有必须先走到终点再到后边拿J再回来的情况。

1
4 3 100
JJJ
JSJ
JEJ
JJJ

我的思路构建一开始对于所有要考虑到的情况来讲,应该是有问题的,但是交了一发AC了,看来我的思路和出题人的想考察的点应该是对上了,虽然出题人对于这个题的数据也可以说是有纰漏了,不过既然我对上了出题人的出题角度了,咱AC了,也拿出来给大家说说0.0

既然这个题后台数据和题干有些纰漏,不过不要太纠结细节,AC了就好。


我的思路是这样滴: 

无非数据结果的范围也就是0----4,要么不需要封锁,要么封锁几个关键点,要么最多封锁四个点,也就是出口或者是入口周围的四个点,直接封锁了这几个点就一定不可能使得小偷完成任务了,所以我们直接BFS+枚举情况

1、封锁一个点,

2、封锁两个点,

3、封锁三个点,如果封锁三个点也不行,那么直接输出4.

时间复杂度:最大:8*8*8*8*8*8(枚举三个点)*8*8(BFS);

既然这样的思路AC了,那么出题人的后台数据也就保证了没有SE紧挨的情况。


然后一点点枚举,细心一点即可。


AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct zuobiao
{
    int x,y,output,time;
}now,nex;
int n,m,t,ok,sx,sy;
char a[10][10];
int vis[10][10][100];
int fx[4]={0,0,1,-1};
int fy[4]={1,-1,0,0};
void Bfs(int x,int y)
{
    queue<zuobiao >s;
    memset(vis,0,sizeof(vis));
    now.x=x;
    now.y=y;
    now.output=0;
    now.time=0;
    vis[x][y][0]=1;
    s.push(now);
    while(!s.empty())
    {
        now=s.front();
        if(a[now.x][now.y]=='E'&&now.output>0)
        {
            ok=1;
            return ;
        }
        s.pop();
        for(int i=0;i<4;i++)
        {
            nex.x=now.x+fx[i];
            nex.y=now.y+fy[i];
            nex.time=now.time+1;
            if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&a[nex.x][nex.y]!='#'&&nex.time<=t)
            {
                if(a[nex.x][nex.y]=='J')
                {
                    nex.output=now.output+1;
                }
                else nex.output=now.output;
                if(vis[nex.x][nex.y][nex.output]==0)
                {
                    vis[nex.x][nex.y][nex.output]=1;
                    s.push(nex);
                }
            }
        }
    }
    return ;
}
int solve()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(a[i][j]=='#')continue;
            if(a[i][j]=='S')continue;
            if(a[i][j]=='E')continue;
            char tmp=a[i][j];
            a[i][j]='#';
            ok=0;
            Bfs(sx,sy);
            a[i][j]=tmp;
            if(ok==0)return 1;
        }
    }
    return 0;
}
int solve2()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(a[i][j]=='#')continue;
            if(a[i][j]=='S')continue;
            if(a[i][j]=='E')continue;
            for(int k=0;k<n;k++)
            {
                for(int l=0;l<m;l++)
                {
                    if(a[k][l]=='#')continue;
                    if(a[k][l]=='S')continue;
                    if(a[k][l]=='E')continue;
                    char tmp1=a[i][j];
                    char tmp2=a[k][l];
                    a[i][j]='#';a[k][l]='#';
                    ok=0;
                    Bfs(sx,sy);
                    a[i][j]=tmp1;a[k][l]=tmp2;
                    if(ok==0)return 1;
                }
            }
        }
    }
    return 0;
}
int solve3()
{
    for(int x1=0;x1<n;x1++)
    {
        for(int y1=0;y1<m;y1++)
        {
            if(a[x1][y1]=='#')continue;
            if(a[x1][y1]=='S')continue;
            if(a[x1][y1]=='E')continue;
            for(int x2=0;x2<n;x2++)
            {
                for(int y2=0;y2<m;y2++)
                {
                    if(a[x2][y2]=='#')continue;
                    if(a[x2][y2]=='S')continue;
                    if(a[x2][y2]=='E')continue;
                    for(int x3=0;x3<n;x3++)
                    {
                        for(int y3=0;y3<m;y3++)
                        {
                            if(a[x3][y3]=='#')continue;
                            if(a[x3][y3]=='S')continue;
                            if(a[x3][y3]=='E')continue;
                            char tmp1=a[x1][y1];
                            char tmp2=a[x2][y2];
                            char tmp3=a[x3][y3];
                            a[x1][y1]='#';
                            a[x2][y2]='#';
                            a[x3][y3]='#';
                            ok=0;
                            Bfs(sx,sy);
                            a[x1][y1]=tmp1;
                            a[x2][y2]=tmp2;
                            a[x3][y3]=tmp3;
                            if(ok==0)return 1;
                        }
                    }
                }
            }
        }
    }
}
int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--)
    {
        scanf("%d%d%d",&n,&m,&t);
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
            for(int j=0;j<n;j++)
            {
                if(a[i][j]=='S')
                {
                    sx=i;sy=j;
                }
            }
        }
        ok=0;
        Bfs(sx,sy);
        if(ok==0)
        {
            printf("0\n");
        }
        else
        {
            if(solve()==1)
            {
                printf("1\n");
                continue;
            }
            if(solve2()==1)
            {
                printf("2\n");
                continue;
            }
            if(solve3()==1)
            {
                printf("3\n");
                continue;
            }
            printf("4\n");
        }
    }
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值