博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
10.28T7 位运算+记忆化+DLZ常数剪枝
阅读量:7113 次
发布时间:2019-06-28

本文共 2873 字,大约阅读时间需要 9 分钟。

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
2 #include
3 #include
4 #include
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<

over

转载于:https://www.cnblogs.com/saionjisekai/p/9867616.html

你可能感兴趣的文章
JDBC实例代码
查看>>
通过setSystemUiVisibility实现状态栏跟Activity之间的位置关系
查看>>
Android中的单位
查看>>
PHP:php中的双引号和单引号的区别
查看>>
PersistenceContext.properties()
查看>>
中国的UED们
查看>>
【Python】python 2 map() reduce()
查看>>
阿里云域名备案之如何填写真实性核验单
查看>>
查询设计分析
查看>>
OpenWRT/LEDE长期运行记录截图
查看>>
执行计划--WHERE条件的先后顺序对执行计划的影响
查看>>
F - 概率(经典问题)
查看>>
不老的神器:安全扫描器Nmap渗透使用指南【转】
查看>>
Java-NIO(六):Channel聚集(gather)写入与分散(scatter)读取
查看>>
CUBA如何新增ServiceBean
查看>>
【技术文档】jeecg3.7-maven搭建好开发环境入门
查看>>
centos7 关闭firewall安装iptables并配置
查看>>
搜索7--noi1804:小游戏
查看>>
聊一聊分布式锁的设计
查看>>
模运算的规则
查看>>