【luogu4011】孤岛营救问题(拯救大兵瑞恩) [最短路][分层思想]
我可能是个废人 按着书上打都能搞一上午
好像是个网络流的题 还在网络流24题里 结果没一个写网络流 要不是bfs要不就是最短路
想练dijkstra 结果例二就给我来个这个东西 把书上程序spfa改成dijkstra
开始忘了运行build函数然后死活输出-1QAQ 后面又数组开小了 全!都!开!小!了!开!小!了!小!了!
一直都没想过数组小了会和输出答案有关 一直看看看看 看书看程序 然后突然开窍 我是不是数组开小了?然后.......
把每个(X,Y)的单元看作一个点 然后相互联通的单元连一条权值为1的边
然后就是连边了 把图分为2p层 就是状态压缩 每层分别为拥有钥匙的状态 然后根据状态来连边建图。 对于有钥匙的点 就将它向对应有钥匙的点连一条权值为0的边
过程比较玄幻
1 /* 2 id:gww 3 language:C-- 4 Kruskal模版! 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 #define rg register 9 const int N=20,inf=0x3f3f3f3f; 10 int row,line,nk,zk,nw,num[N][N],tot=0; 11 //列 行 钥匙数 门/墙 标号 12 int mp[N*N][N*N],kn[N]; 13 struct key 14 { 15 int x,y; 16 }ky[N][N*N]; 17 inline int rd() 18 { 19 int x=0,w=0;char ch=0; 20 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 21 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 22 return w?-x:x; 23 } 24 25 int head[1000000],cnt=0; 26 struct edge 27 { 28 int v,nxt,w; 29 }e[1000000]; 30 void add(int u,int v,int w) 31 { 32 e[++cnt].v=v; 33 e[cnt].w=w; 34 e[cnt].nxt=head[u]; 35 head[u]=cnt; 36 } 37 38 bool havek[N]; 39 int m,n,layer; 40 void build() 41 { 42 layer=1<<zk,n=tot*layer; 43 //每层节点数 层数 总结点数 44 for(int s=0;s<layer;s++) 45 { 46 for(int i=1;i<=zk;i++)//当前状态是否有钥匙 47 if(s&(1<<(i-1))) havek[i]=1; 48 else havek[i]=0; 49 for(int i=1;i<=row;i++) 50 for(int j=1;j<=line;j++) 51 { 52 int pos1=num[i][j],pos2=num[i][j+1];//向右 53 if(pos2&&mp[pos1][pos2]+1)//有节点且非墙 54 if(!mp[pos1][pos2]||havek[mp[pos1][pos2]])//无门||有钥匙 55 add(pos1+tot*s,pos2+tot*s,1),add(pos2+tot*s,pos1+tot*s,1); 56 pos2=num[i+1][j];//向下 57 if(pos2&&mp[pos1][pos2]+1)//有节点且非墙 58 if(!mp[pos1][pos2]||havek[mp[pos1][pos2]])//无门||有钥匙 59 add(pos1+tot*s,pos2+tot*s,1),add(pos2+tot*s,pos1+tot*s,1); 60 } 61 for(int i=1;i<=zk;i++)//转移到其他状态 62 if(!havek[i])//么得钥匙才转移 63 { 64 int is=(s+(1<<(i-1)));//目标状态 65 for(int j=1;j<=kn[i];j++) 66 { 67 int pos=num[ky[i][j].x][ky[i][j].y]; 68 add(pos+tot*s,pos+tot*is,0); 69 } 70 } 71 } 72 } 73 struct node 74 { 75 int dis,pos; 76 node():dis(0),pos(0){} 77 node(int a,int b):dis(a),pos(b){} 78 bool operator <(const node &x)const 79 {return x.dis<dis;} 80 }; 81 int dis[N<<N];bool vis[N<<N]; 82 priority_queue<node> q; 83 void dij(int x) 84 { 85 for(int i=1;i<=n;i++) dis[i]=inf,vis[i]=0; 86 dis[x]=0;q.push(node(0,x)); 87 while(q.size()) 88 { 89 int u=q.top().pos;q.pop(); 90 if(vis[u]) continue; 91 vis[u]=1; 92 for(int i=head[u];i;i=e[i].nxt) 93 { 94 int v=e[i].v,w=e[i].w; 95 if(dis[v]>dis[u]+w) 96 { 97 dis[v]=dis[u]+w; 98 q.push(node(dis[v],v)); 99 } 100 } 101 } 102 } 103 104 int main() 105 { 106 row=rd(),line=rd(),zk=rd(),nw=rd(); 107 for(rg int i=1;i<=row;i++)//初始化标号 108 for(rg int j=1;j<=line;j++) num[i][j]=++tot; 109 for(int i=1;i<=nw;i++) 110 { 111 int x1=rd(),y1=rd(),x2=rd(),y2=rd(),g=rd(); 112 int pos1=num[x1][y1],pos2=num[x2][y2]; 113 if(g==0) g=-1;//为墙 114 mp[pos1][pos2]=mp[pos2][pos1]=g; 115 } 116 nk=rd(); 117 for(int i=1;i<=nk;i++) 118 { 119 int x=rd(),y=rd(),g=rd(); 120 ky[g][++kn[g]].x=x,ky[g][kn[g]].y=y; 121 } 122 build(); 123 dij(1); 124 int ans=inf; 125 for(int i=0;i<layer;i++) 126 ans=min(ans,dis[i*tot+tot]); 127 if(ans<inf) printf("%d",ans); 128 else printf("-1"); 129 return 0; 130 }