zoukankan      html  css  js  c++  java
  • 孤岛营救与汽车加油行驶问题

      题目链接:https://www.luogu.org/problemnew/show/P4011 (孤岛营救)|| https://www.luogu.org/problemnew/show/P4009 (汽车加油行驶)

     题解:

      两道分层图,所以我放在一起了=-=

      别人都是对状态直接bfs了,我是对每个状态编号、建图,然后跑spfa。(感觉直接bfs好像会快一点,找时间学习一波qwq)

      关于编号的注意事项就是不同点的编号一定不能重复,不然就会出现各种奇奇怪怪的错误。(血的教训啊...

      

    孤岛营救:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<bitset>
     6 #define LL long long
     7 #define RI register int
     8 using namespace std;
     9 const int INF = 0x7ffffff ;
    10 const int N = 10 + 2 ;
    11 const int CC = 100 + 10 ;
    12 const int M = 1e6 + 10 ;
    13 const int NN = 1e6 + 10 ;
    14 
    15 const int cx[] = {-1,0,0,1} ;
    16 const int cy[] = {0,1,-1,0} ;
    17 
    18 inline int read() {
    19     int k = 0 , f = 1 ; char c = getchar() ;
    20     for( ; !isdigit(c) ; c = getchar())
    21       if(c == '-') f = -1 ;
    22     for( ; isdigit(c) ; c = getchar())
    23       k = k*10 + c-'0' ;
    24     return k*f ;
    25 }
    26 struct Edge {
    27     int to, next, val ;
    28 }e[M] ;
    29 int n, m, p, k, t ; int head[NN], dis[NN] ;
    30 int noo[N][N][N][N] ; // 11表示墙,其他数字表示钥匙 
    31 inline void add_edge(int x,int y,int vv) {
    32     static int cnt = 1 ;
    33     e[++cnt].to = y, e[cnt].next = head[x], head[x] = cnt, e[cnt].val = vv ;
    34 }
    35 
    36 inline void spfa() {
    37     for(int i=1;i<=NN;i++) dis[i] = INF ; int s = 1 ;
    38     deque<int>q ; q.push_back(s) ; dis[s] = 0 ; bitset<NN>inq ;
    39     while(!q.empty()) {
    40         int x = q.front() ; q.pop_front() ;
    41         for(int i=head[x];i;i=e[i].next) {
    42             int y = e[i].to ;
    43             if(dis[y] > dis[x]+e[i].val) {
    44                 dis[y] = dis[x]+e[i].val ;
    45                 if(!inq[y]) {
    46                     if(!q.empty() && dis[y] < dis[q.front()]) q.push_front(y) ;
    47                     else q.push_back(y) ;
    48                     inq[y] = 1 ;
    49                 }
    50             }
    51         }
    52         inq[x] = 0 ;
    53     }
    54     if(dis[t] == INF) printf("-1") ;
    55     else printf("%d",dis[t]) ;
    56 }
    57 
    58 int main() {
    59     n = read(), m = read(), p = read(), k = read() ; t = NN-10 ;
    60     int x1, y1, x2, y2, ii ;
    61     for(int i=1;i<=k;i++) {
    62         x1 = read(), y1 = read(), x2 = read(), y2 = read(), ii = read() ;
    63         if(!ii) {
    64             noo[x1][y1][x2][y2] = noo[x2][y2][x1][y1] = 11 ;
    65         } else noo[x1][y1][x2][y2] = noo[x2][y2][x1][y1] = ii ;
    66     }
    67     for(int s=0;s<(1<<p);s++) {  
    68         for(int i=1;i<=n;i++) {
    69             for(int j=1;j<=m;j++) {
    70                 int p = s*CC + (i-1)*m + j ;
    71                 for(int k=0;k<4;k++) {
    72                     int xx = i+cx[k], yy = j+cy[k] ;
    73                     if(!xx || !yy || xx > n || yy > m) continue ;
    74                     int pp = s*CC + (xx-1)*m + yy ;
    75                     if( !noo[i][j][xx][yy] || (s&(1<<(noo[i][j][xx][yy]-1))) ) 
    76                       add_edge(p,pp,1), add_edge(pp,p,1) ;
    77                 }
    78             }
    79         }
    80     }
    81     int nn = read() ;
    82     for(int i=1;i<=nn;i++) {
    83         int x = read(), y = read(), kk = read() ;
    84         for(int s=0;s<(1<<p);s++) {
    85             if(!(s&(1<<(kk-1)))) { // 没有该钥匙的状态可以转移到有该钥匙的状态 
    86                 int p1 = s*CC + (x-1)*m + y, p2 = (s^(1<<(kk-1)))*CC + (x-1)*m + y ;
    87                 add_edge(p1,p2,0) ;
    88             }
    89         }
    90     }
    91     for(int s=0;s<(1<<p);s++) add_edge(s*CC+n*m,t,0) ;
    92     spfa() ;
    93     return 0 ;
    94 }

    汽车加油行驶:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #include<bitset>
      6 #define LL long long
      7 #define RI register int
      8 using namespace std;
      9 const int INF = 0x7ffffff ;
     10 const int CC = 1e4 + 100 ;
     11 const int N = 100 + 10 ;
     12 const int NN = 1e6 + 10 ;
     13 const int M = 1e6 + 10 ;
     14 
     15 const int cx1[] = {-1,0} ;
     16 const int cy1[] = {0,-1} ;
     17 const int cx2[] = {1,0} ;
     18 const int cy2[] = {0,1} ;
     19 
     20 inline int read() {
     21     int k = 0 , f = 1 ; char c = getchar() ;
     22     for( ; !isdigit(c) ; c = getchar())
     23       if(c == '-') f = -1 ;
     24     for( ; isdigit(c) ; c = getchar())
     25       k = k*10 + c-'0' ;
     26     return k*f ;
     27 }
     28 struct Edge {
     29     int to, next, val ;
     30 }e[M] ;
     31 int n, k, a, b, c, s, t ; int head[NN], dis[NN] ;
     32 bool hh[N][N] ;
     33 inline void add_edge(int x,int y,int vv) {
     34     static int cnt = 0 ;
     35     e[++cnt].to = y, e[cnt].next = head[x], head[x] = cnt, e[cnt].val = vv ;
     36 }
     37 
     38 inline void spfa() {
     39     for(int i=1;i<=NN;i++) dis[i] = INF ;
     40     deque<int>q ; q.push_back(s) ; dis[s] = 0 ; bitset<NN>inq ; inq[s] = 1 ;
     41     while(!q.empty()) {
     42         int x = q.front() ; q.pop_front() ;
     43         for(int i=head[x];i;i=e[i].next) {
     44             int y = e[i].to ;
     45             if(dis[y] > dis[x]+e[i].val) {
     46                 dis[y] = dis[x]+e[i].val ;
     47                 if(!inq[y]) {
     48                     inq[y] = 1 ;
     49                     if(!q.empty() && dis[y] < dis[q.front()]) q.push_front(y) ;
     50                     else q.push_back(y) ;
     51                 }
     52             }
     53         }
     54         inq[x] = 0 ;
     55     }
     56     printf("%d",dis[t]) ;
     57 }
     58 
     59 int main() {
     60 //    freopen("trav.in","r",stdin) ;
     61 //    freopen("trav.out","w",stdout) ;
     62     n = read(), k = read(), a = read(), b = read(), c = read() ; t = (k+1)*CC + 10 ;
     63     for(int i=1;i<=n;i++) 
     64       for(int j=1;j<=n;j++) hh[i][j] = read() ;
     65     for(int now=k;now;now--) {
     66         for(int i=1;i<=n;i++) {
     67             for(int j=1;j<=n;j++) {
     68                 if(!hh[i][j]) { // 无加油站 
     69                     for(int kk=0;kk<2;kk++) {
     70                         int xx = i+cx1[kk], yy = j+cy1[kk] ;
     71                         if(!xx || !yy || xx > n || yy > n) continue ;
     72                         add_edge(now*CC+(i-1)*n+j,(now-1)*CC+(xx-1)*n+yy,b) ;
     73                     }
     74                     for(int kk=0;kk<2;kk++) {
     75                         int xx = i+cx2[kk], yy = j+cy2[kk] ;
     76                         if(!xx || !yy || xx > n || yy > n) continue ;
     77                         add_edge(now*CC+(i-1)*n+j,(now-1)*CC+(xx-1)*n+yy,0) ;
     78                     }
     79                 } else { // 有加油站 
     80                     for(int kk=0;kk<2;kk++) {
     81                         int xx = i+cx1[kk], yy = j+cy1[kk] ;
     82                         if(!xx || !yy || xx > n || yy > n) continue ;
     83                         add_edge(now*CC+(i-1)*n+j,(k-1)*CC+(xx-1)*n+yy,b+a) ;
     84                     }
     85                     for(int kk=0;kk<2;kk++) {
     86                         int xx = i+cx2[kk], yy = j+cy2[kk] ;
     87                         if(!xx || !yy || xx > n || yy > n) continue ;
     88                         add_edge(now*CC+(i-1)*n+j,(k-1)*CC+(xx-1)*n+yy,a) ;
     89                     }                    
     90                 }
     91                 // 创造加油站 =-= 
     92                 for(int kk=0;kk<2;kk++) {
     93                     int xx = i+cx1[kk], yy = j+cy1[kk] ;
     94                     if(!xx || !yy || xx > n || yy > n) continue ;
     95                     add_edge(now*CC+(i-1)*n+j,(k-1)*CC+(xx-1)*n+yy,a+b+c) ;
     96                 }
     97                 for(int kk=0;kk<2;kk++) {
     98                     int xx = i+cx2[kk], yy = j+cy2[kk] ;
     99                     if(!xx || !yy || xx > n || yy > n) continue ;
    100                     add_edge(now*CC+(i-1)*n+j,(k-1)*CC+(xx-1)*n+yy,a+c) ;
    101                 }
    102             }
    103         }
    104     }
    105     for(int i=1;i<=n;i++) 
    106       for(int j=1;j<=n;j++) {
    107            if(!hh[i][j]) {
    108                for(int kk=0;kk<2;kk++) {
    109                    int xx = i+cx1[kk], yy = j+cy1[kk] ;
    110                    if(!xx || !yy || xx > n || yy > n) continue ;
    111                    add_edge(n*(i-1)+j,(k-1)*CC+(xx-1)*n+yy,c+b+a) ;
    112                }
    113                for(int kk=0;kk<2;kk++) {
    114                    int xx = i+cx2[kk], yy = j+cy2[kk] ;
    115                    if(!xx || !yy || xx > n || yy > n) continue ;
    116                    add_edge(n*(i-1)+j,(k-1)*CC+(xx-1)*n+yy,c+a) ;                   
    117                }
    118            } else {
    119                for(int kk=0;kk<2;kk++) {
    120                    int xx = i+cx1[kk], yy = j+cy1[kk] ;
    121                    if(!xx || !yy || xx > n || yy > n) continue ;
    122                    add_edge(n*(i-1)+j,(k-1)*CC+(xx-1)*n+yy,b+a) ;
    123                }
    124                for(int kk=0;kk<2;kk++) {
    125                    int xx = i+cx2[kk], yy = j+cy2[kk] ;
    126                    if(!xx || !yy || xx > n || yy > n) continue ;
    127                    add_edge(n*(i-1)+j,(k-1)*CC+(xx-1)*n+yy,a) ;                   
    128                }
    129            }           
    130       }
    131     for(int now=k;now>=0;now--) add_edge(now*CC+n*n,t,0) ; s = k*CC + 1 ;
    132     spfa() ;
    133     return 0 ;
    134 }
  • 相关阅读:
    poj3614 Sunscreen 题解报告
    poj2299 Ultra-QuickSort 题解报告
    poj3784 Running Median 题解报告(对顶堆)
    CH103 Cinema 题解报告
    poj1845 Sumdiv 题解报告
    poj2018 Best Cow Fences 题解报告
    $CF311B Cats Transport$ 斜率优化
    斜率优化入门题:任务安排$123$ : )
    $Poj1821 Fence $单调队列优化$DP$
    《算法竞赛》$0×00$基本算法
  • 原文地址:https://www.cnblogs.com/zub23333/p/8697201.html
Copyright © 2011-2022 走看看