特殊迷宫
来源:互联网 发布:修改游戏的软件 编辑:程序博客网 时间: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;}