openjudge 拯救公主

点击打开题目

看到这道题,第一感觉是我有一句 m2p 不知当讲不当讲
传送门就算了,你提莫还来宝石,还不给我每种最多有几个~~

在一般的迷宫问题里,无论已经走了多少步,只要到达同一个点,状态便是等价的,但在这道题中,当持有不同种类宝石到达同一个地方,可能对结果会有影响,那就在BFS的地图中多开一维,来存宝石的状态

200·200的地图,DFS就算了,但BFS宝石的状态怎么办?
细看一下,宝石只有五种,凑齐k种不计个数,就可救出公主

用二进制五位,即十进制32即可解决,二进制中的每一位表示一种宝石是否获得

代码实现,就看自己的修行了,反正我写完时,第一感觉是我有一句 m2p 现在就要讲

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
struct node{int x,y,dmt,step;};
queue<node>Q;
int m,n,k;
bool v[201][201][32];
int map[201][201],u[4]={-1,1,0,0},z[4]={0,0,-1,1};
int d[11][2],dcnt,xz,yz;
int getint()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    return num*flag;
}
bool check1(int s,int x)
{
    int i;
    while(s&&++i)
    {
        if(s&1&&i==x)return 1;
        s/=2;
    }
    return 0;
}
bool check2(int s)
{
    int z=0;
    while(s)z+=(s&1),s/=2;
    if(z>=k)return 1;
    return 0;
}
int main()
{
    int tt=getint(),i,j;
    char c;
    while(tt--)
    {
        memset(v,0,sizeof v);memset(map,0,sizeof map);
        memset(d,0,sizeof d);dcnt=0;
        while(!Q.empty())Q.pop();
        m=getint(),n=getint(),k=getint();
        for(i=1;i<=m;i++)for(j=1;j<=n;j++)
        {
            c=getchar();
            if(c=='\n'){j--;continue;}
            if(c=='#')map[i][j]=-1;
            if(c>='0'&&c<='9')map[i][j]=c-47;
            if(c=='$')d[++dcnt][0]=i,d[dcnt][1]=j,map[i][j]=6;
            if(c=='S'){node t;t.x=i,t.y=j,t.dmt=0,t.step=0;Q.push(t);v[i][j][0]=1;}
            if(c=='E')xz=i,yz=j;
        }

        while(!Q.empty())
        {
            node t=Q.front();Q.pop();
            for(i=0;i<4;i++)
                if(map[t.x+u[i]][t.y+z[i]]!=-1&&t.x+u[i]>0&&t.x+u[i]<=m&&t.y+z[i]>0&&t.y+z[i]<=n)
                {
                    node w;w.x=t.x+u[i],w.y=t.y+z[i],w.dmt=t.dmt,w.step=t.step+1;
                    if(map[w.x][w.y]==6)
                        for(j=1;j<=dcnt;j++)
                            if(!v[d[j][0]][d[j][1]][w.dmt])
                            {
                                node hh;
                                hh.x=d[j][0],hh.y=d[j][1],hh.dmt=w.dmt,hh.step=w.step;
                                Q.push(hh);
                            }
                    if(!map[w.x][w.y]&&!v[w.x][w.y][w.dmt])
                        v[w.x][w.y][w.dmt]=1,Q.push(w);
                    if(map[w.x][w.y]>0&&map[w.x][w.y]<6)
                    {
                        if(!check1(w.dmt,map[w.x][w.y]))w.dmt+=int(pow(2*1.0,map[w.x][w.y]-1));
                        if(!v[w.x][w.y][w.dmt])
                        {
                            v[w.x][w.y][w.dmt]=1;
                            Q.push(w);
                        }
                    }
                    if(w.x==xz&&w.y==yz)
                        if(check2(w.dmt))
                            {printf("%d\n",w.step);goto hehe;}
                }
        }
        printf("oop!\n");
        hehe:;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值