10.28T7 位运算+记忆化+DLZ常数剪枝

5170 -- 【11.05题目】密室

Description

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

Input

  第一行三个整数 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 种钥匙。

Output

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

Sample Input

3 3 2
1 0
0 1
0 0
1 3 1 1
1 2 1 0
2 3 1 1

Sample Output

2

Hint

 
 
 
 
 
直接记忆化每个点在某个状态的值可以强力剪枝,如果直接爆搜直接爆栈,最后加上DLZ的5000000运算次数以上就剪掉就过了。。。
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #define N 100000
 6 using namespace std;
 7 int tot;
 8 struct node {
 9     long long u,v,w;
10 } e[N];
11 long long first[N],nxt[N],cnt,room[N];
12 void add(long long u,long long v,long long w) {
13     e[++cnt].u=u;
14     e[cnt].v=v;
15     e[cnt].w=w;
16     nxt[cnt]=first[u];
17     first[u]=cnt;
18 }
19 long long n,m,k;
20 long long min0=20020731;
21 int f[5001][2000];
22 void dfs(long long x,long long now,long long step) {
23     tot++;
24     if(tot>=5000000)return;
25     if(step>=min0)return;
26     if(f[x][now]<=step)return;
27     f[x][now]=step;
28     if(x==n) {
29         min0=min(min0,step);
30         return;
31     }
32     for(long long i=first[x];i;i=nxt[i]){
33         long long v=e[i].v;
34         if((now&e[i].w)!=e[i].w)continue;
35         long long temp=now|room[v];
36         dfs(v,temp,step+1);
37         if(tot>=5000000)return;
38     }
39 }
40 long long read(){
41     long long x=0,f=1;
42     char c=getchar();
43     while(!isdigit(c)){
44         if(c=='-')f=-1;
45         c=getchar();
46     }
47     while(isdigit(c)){
48         x=(x<<3)+(x<<1)+c-'0';
49         c=getchar();
50     }
51     return x*f;
52 }
53 int main() {
54     int siz=80<<20;
55     __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(siz)+siz));
56     n=read(),m=read(),k=read();
57     for(long long i=1; i<=n; i++) {
58         for(long long j=1; j<=k; j++) {
59             long long x;
60             x=read();
61             room[i]=room[i]*2+x;
62         }
63     }
64     for(long long i=1; i<=m; i++) {
65         long long now=0;
66         long long a,b;
67         a=read(),b=read();
68         for(long long j=1; j<=k; j++) {
69             long long x;
70             x=read();
71             now=now*2+x;
72         }
73         add(a,b,now);
74     }
75     memset(f,0x3f3f3f3f,sizeof f);
76     dfs(1,room[1],0);
77     if(min0==20020731){
78         cout<<"No Solution";
79     }
80     else{
81         cout<<min0;
82     }
83     exit(0);
84     return 0;
85 }

over

posted @ 2018-10-28 22:15  saionjisekai  阅读(243)  评论(0编辑  收藏  举报