特殊迷宫

来源:互联网 发布:修改游戏的软件 编辑:程序博客网 时间:2024/05/21 21:38

【问题描述】

  小沐正处在一个特殊的迷宫里,他希望能尽快走出迷宫。
  该迷宫中有N个房间,初始时,小沐在1号房间,而出口在N号房间。迷宫的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间X到房间Y的通道。另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过)。幸运的是,钥匙在打开传送门的封印后,并不会消失。
  然而,通过迷宫的传送门需要耗费大量的时间,因此,小沐希望通过尽可能少的传送门到达出口,你能告诉小沐这个数值吗?另外,小沐有可能不能逃出这个迷宫,如果是这样,请输出 “No Solution”。

【输入格式】

  输入的第一行三个整数 N,M,K,分别表示房间的数量、传送门的数量以及钥匙的种类数。接下来N行,每行K个0或1,若第i个数为1,则表示该房间内有第i种钥匙,若第i个数为0,则表示该房间内没有第i种钥匙。再接下来M行,每行先读入两个整数X,Y,表示该传送门是建立在X号房间,通向Y号房间的,再读入K个0或1,若第i个数为1,则表示通过该传送门需要i种钥匙,若第i个数为0,则表示通过该传送门不需要第i种钥匙。

【输出格式】

  输出一行一个 “No Solution”,或一个整数,表示最少通过的传送门数。

【输入样例】

【样例1】
 3 3 2
 1 0
 0 1
 0 0
 1 3 1 1
 1 2 1 0
 2 3 1 1

【样例2】
 20 40 0
 10 18
 18 14
 19 13
 4 14
 13 10
 5 18
 14 1
 13 13
 10 16
 19 11
 11 15
 10 18
 5 8
 12 19
 7 8
 18 6
 14 5
 9 5
 2 17
 13 14
 18 15
 8 18
 7 1
 13 5
 4 6
 17 4
 1 4
 10 10
 13 8
 19 2
 4 9
 3 3
 5 10
 17 5
 12 8
 19 11
 3 16
 17 10
 18 16
 13 13

【样例3】
 20 50 0
 8 10
 7 17
 5 11
 14 20
 20 16
 8 19
 12 11
 18 7
 17 5
 4 15
 16 11
 11 8
 10 12
 8 9
 16 8
 3 16
 1 6
 3 20
 6 10
 11 12
 6 8
 18 17
 14 17
 3 11
 4 19
 9 2
 8 6
 13 2
 5 2
 12 19
 8 10
 14 7
 6 12
 6 4
 13 2
 8 7
 13 19
 17 9
 3 14
 18 20
 2 14
 4 17
 20 15
 14 15
 2 15
 7 20
 12 12
 18 10
 15 9
 15 9

【输出样例】

【样例1】
 2

【样例2】
 No Solution
【样例3】
 4
 思路:
 题本身很简单。此题唯一的收获在于压缩,将所得的压缩二进制成整数。
 

#include<cstdio>#include<iostream>#include<algorithm>#include<cctype>#include<cstring>#include<queue>#include<cmath>using namespace std;#define maxn 5005#define maxm 6005struct edge{    int to,next,w;}e[maxm<<1];int first[maxn],np=0,dist[maxn][2050],a[15];int n,m,k,key[maxn];bool inq[maxn][2050];const int inf=1e7;void addedge(int u,int v,int w){    e[++np]=(edge){v,first[u],w};    first[u]=np;}struct data{    int id,key;};int calc(int x,int y){    int ans=0;    memset(a,0,sizeof(a));    for (int i=0;i<k;i++)    {        if (x%2==1||y%2==1)        a[i]=1;        x=x/2,y=y/2;    }    for (int i=0;i<k;i++)    ans+=(a[i]<<i);    return ans;}bool calc1(int x,int y){    for (int i=0;i<k;i++)    {        if (x%2==0&&y%2==1)        return 0;        x=x/2,y=y/2;    }    return 1;}void BFS(){    data t;    queue<data>q;    inq[1][key[1]]=1;    dist[1][key[1]]=0;    q.push((data){1,key[1]});    while(!q.empty())    {        t=q.front();        q.pop();        int i=t.id;        for (int p=first[i];p;p=e[p].next)        {            int j=e[p].to,w=e[p].w;            if (!calc1(t.key,w))            continue;            int ww=calc(t.key,key[j]);            if (inq[j][ww])            continue;            dist[j][ww]=dist[i][t.key]+1;            inq[j][ww]=1;            q.push((data){j,ww});        }    }}void init(){    int x,u,v;    scanf("%d%d%d",&n,&m,&k);    for (int i=1;i<=n;i++)    {        int di=0;        for (int j=0;j<k;j++)        {            scanf("%d",&x);            if (x==1)            di+=(x<<j);        }        key[i]=di;        //printf("%d\n",di);    }    for (int i=1;i<=m;i++)    {        scanf("%d%d",&u,&v);        int di=0;        for (int j=0;j<k;j++)        {            scanf("%d",&x);            if (x==1)            di+=(x<<j);        }        //printf("%d\n",di);        addedge(u,v,di);    }}void solve(){    int ans=1e7;    BFS();    int kk=(1<<(k+1))-1;    for (int i=0;i<=kk;i++)    if (ans>dist[n][i]&&dist[n][i]!=0)    ans=dist[n][i];    if (ans!=1e7)    printf("%d",ans);    else    printf("No Solution");}int main(){    //freopen("maze.in","r",stdin);    //freopen("maze.out","w",stdout);    //freopen("in.txt","r",stdin);    init();    solve();    return 0;}
原创粉丝点击