• bzoj1066题解


    【解题思路】

      考虑拆点,把每根石柱拆成两个点,具体可以理解为石柱底部和石柱顶部,能爬到石柱顶部的蜥蜴只有有限只,而且蜥蜴只有爬到了石柱顶部才能跳到其他石柱的底部。

      这样,考虑如下建图:

      将每个有蜥蜴的石柱底部和源点连边,容量为1;

      将每个可以跳出边界的石柱顶部和汇点连边,容量为∞;

      将每根石柱顶底相连,容量为该石柱最大承受蜥蜴个数;

      将可以相互跳达的任意两根石柱顶底相连,容量为∞。

      这样,该图的最大流即为最多可逃脱蜥蜴数,最终答案即为总蜥蜴数-最大流,复杂度o(r3c3d2)。

    【参考代码】

      1 #include <bits/stdc++.h>
      2 #define range(i,low,high) for(register int i=(low);i<(high);++i)
      3 #define dange(i,high,low) for(register int i=(high);i>(low);--i)
      4  
      5 //#define __debug
      6 #ifdef __debug
      7     #define __function__(type) type
      8     #define __procedure__      void
      9 #else
     10     #define __function__(type) __attribute__((optimize("-O2"))) inline type
     11     #define __procedure__      __attribute__((optimize("-O2"))) inline void
     12 #endif
     13  
     14 using namespace std;
     15  
     16 static const int N=800,M=50000,INF=0x7f7f7f7f;
     17 static int r,c,d,cardE=0; int hed[N+5],h[25][25];
     18  
     19 struct edge
     20 {
     21     int fr,to,cap,nxt;
     22     edge(
     23         const int&f=0,const int&t=0,
     24         const int&c=0,const int&x=0
     25     ):fr(f),to(t),cap(c),nxt(x) {}
     26 }edg[M<<2|3];
     27  
     28 __procedure__ addedge(
     29     const int&fr,const int&to,const int&cp
     30 )
     31 {
     32     edg[cardE]=edge(fr,to,cp,hed[fr]),hed[fr]=cardE++;
     33 }
     34 __procedure__ add_edge(
     35     const int&fr,const int&to,const int&cp
     36 )
     37 {
     38     addedge(fr,to,cp),addedge(to,fr,0);
     39 }
     40  
     41 //SAP {
     42 static const int S=0,T=801;
     43 int aug[N+5],cur[N+5],dis[N+5],gap[N+5],path[N+5];
     44  
     45 __function__(int) augment()
     46 {
     47     for(int i=T;i!=S;i=edg[path[i]].fr)
     48     {
     49         edg[path[i]].cap-=aug[T],edg[path[i]^1].cap+=aug[T];
     50     }
     51     return aug[T];
     52 }
     53  
     54 __function__(int) SAP(const int&N)
     55 {
     56     memset(aug,0,sizeof aug),memset(gap,0,sizeof gap);
     57     memset(dis,0,sizeof dis),aug[S]=INF,gap[0]=N; int ret=0;
     58     range(i,1,max(N,T)+1) cur[i]=hed[i];
     59     for(int fr=S;dis[S]<N;)
     60     {
     61         if(fr==T) fr=S,ret+=augment(); bool flag=1;
     62         for(int i=cur[fr];~i;i=edg[i].nxt)
     63         {
     64             int to=edg[i].to;
     65             if(edg[i].cap&&dis[fr]==dis[to]+1)
     66             {
     67                 aug[to]=min(aug[fr],edg[i].cap),
     68                 path[to]=cur[fr]=i,fr=to,flag=0; break;
     69             }
     70         }
     71         if(flag)
     72         {
     73             if(!--gap[dis[fr]]) break; dis[fr]=N;
     74             for(int i=hed[fr];~i;i=edg[i].nxt) if(edg[i].cap)
     75             {
     76                 dis[fr]=min(dis[fr],dis[edg[i].to]+1);
     77             }
     78             ++gap[dis[fr]],cur[fr]=hed[fr];
     79             if(fr!=S) fr=edg[path[fr]].fr;
     80         }
     81     }
     82     return ret;
     83 }
     84 //} SAP
     85  
     86 __function__(bool) ok(const int&x,const int&y)
     87 {
     88     return x+d>=r||x<d||y+d>c||y<=d;
     89 }
     90  
     91 __function__(int) calc(const int&x,const int&y,const bool&up)
     92 {
     93     return x*c+y+up*(N>>1);
     94 }
     95  
     96 int main()
     97 {
     98     scanf("%d%d%d",&r,&c,&d); int cnt=0;
     99     memset(hed,-1,sizeof hed);
    100     range(i,0,r) range(j,1,c+1)
    101     {
    102         while(!isdigit(h[i][j]=getchar()));
    103         add_edge(calc(i,j,0),calc(i,j,1),h[i][j]-='0');
    104     }
    105     range(i,0,r) range(j,1,c+1)
    106     {
    107         char ch=getchar();
    108         for(;ch!='.'&&ch!='L';ch=getchar());
    109         if(ch=='L') add_edge(S,calc(i,j,0),1),++cnt;
    110     }
    111     range(i,0,r) range(j,1,c+1) if(ok(i,j))
    112     {
    113         add_edge(calc(i,j,1),T,INF);
    114     }
    115     range(i,0,r) range(j,1,c+1) range(k,-d,d+1)
    116     {
    117         int rest=d-abs(k);
    118         range(l,-rest,rest+1) if(k||l)
    119         {
    120             int x=i+k,y=j+l;
    121             if(x>=0&&x<r&&y>0&&y<=c&&h[i][j]&&h[x][y])
    122             {
    123                 add_edge(calc(i,j,1),calc(x,y,0),INF);
    124             }
    125         }
    126     }
    127     return printf("%d
    ",cnt-SAP(r*c+1<<1)),0;
    128 }
    View Code
  • 相关阅读:
    The 4 Most Important Skills for a Software Developer
    Youth is not a time of life, it is a state of mind——青春不是一段年华,而是一种心境
    英雄所见略同——每个人都有的一套价值体系观念
    28法则————10分钟休息胜过半小时努力
    离职员工心声
    员工必备素质、能力——职场精英
    安卓sqlite数据库的使用
    安卓adb命令的使用
    windows使用命令行,提高效率
    命令行编译java文件(含第三方jar包)
  • 原文地址:https://www.cnblogs.com/spactim/p/6634407.html
Copyright © 2020-2023  润新知