【问题描述】
小沐正处在一个特殊的迷宫里,他希望能尽快走出迷宫。
该迷宫中有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 6005
struct 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;
}