• 【luogu4011】孤岛营救问题(拯救大兵瑞恩) [最短路][分层思想]


    P4011 孤岛营救问题

    我可能是个废人 按着书上打都能搞一上午

    好像是个网络流的题 还在网络流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 }

  • 相关阅读:
    Spring4
    Mysql索引优化、JMM内存模型
    深入浅出JVM
    ZGC垃圾搜集器
    Hibernate4基础
    红楼梦 各版本及资料
    JavaME环境配置
    5.1 Intent
    4.3 异步任务
    4.2.2 网络编程之Socket
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/10417489.html
Copyright © 2020-2023  润新知