hdu 2732

有一个方格 , 方格里面的每个格子要么是无底洞 , 要么有一根竖着m米长的棍子 , 现在在方格里面的某些棍子上面有青蛙 , 保证每个棍子上面只有一个 ,每只青蛙都要想办法跳跃出去 , 即跳到方格外面 ,  现在告诉你青蛙的最大跳跃距离 , 并且对于每根棍子, 在青蛙跳跃后, 棍子的长度将减一, 问你至少还有多少只青蛙无法跳跃出去 。 

 

可以用最大流求解 , 考虑如何建图, 已知的有青蛙 ,和棍子 , 还有棍子的长度, 对于最大流求解问题时 , 建的图 ,往往都是考虑的边 , 给边赋值 , 但这个题目里面 , 棍子的长度是相同于棍子而已, 那么如何在图上  把 青蛙跳跃后棍子长度减一这个动作 表示出来 , 于是可以考虑拆点 ,把每根棍子拆成两个点,并且在两个点之间连上边 , 边的大小为棍子的长度 , 这样青蛙每跳跃一下 , 两点之间的边值减一, 这样, 青蛙跳跃的动作就表现出来了, 剩下的连边就是最普通的了。

 

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<cstring>
  5 #include<cmath>
  6 
  7 using namespace std ;
  8 
  9 const int N = 2222 ;
 10 
 11 struct node{
 12     int u , v , val , next ;
 13 };
 14 
 15 node edge[111111] ;
 16 
 17 char map1[22][22] , map2[22][22]  ;
 18 int dist[N] , s , t , first[N] ;
 19 int n , d_len , m , e_num ;
 20 
 21 void init()
 22 {
 23     e_num = 0 ;
 24     memset( first , -1 , sizeof(first) ) ;
 25 }
 26 
 27 void _Insert( int u , int v , int num )
 28 {
 29     edge[++e_num].u = u ; edge[e_num].v = v ;
 30     edge[e_num].val = num ;
 31 
 32     edge[e_num].next = first[u] ;
 33     first[u] = e_num ;
 34 }
 35 
 36 void Insert( int u , int v , int num ){
 37     _Insert( u , v , num ) ;
 38     _Insert( v , u , 0 ) ;
 39 }
 40 
 41 bool bfs()
 42 {
 43     memset( dist , -1 , sizeof(dist) ) ;
 44     dist[s] = 0 ;
 45 
 46     queue<int>Q ;
 47     Q.push(s) ;
 48 
 49     while( !Q.empty() )
 50     {
 51         int u = Q.front() ; Q.pop() ;
 52         int f ;
 53 
 54         f = first[u] ;
 55 
 56         while( f!=-1 ){
 57             int  v = edge[f].v , val = edge[f].val ;
 58 
 59             if( dist[v]==-1 && val>0 )
 60                     dist[v] = dist[u] + 1 ,
 61                     Q.push(v) ;
 62             f = edge[f].next ;
 63         }
 64     }
 65 
 66     if( dist[t]==-1 ) return false ;
 67     return true ;
 68 }
 69 
 70 int Dfs( int x , int len )
 71 {
 72     if( x==t ) return len ;
 73 
 74     int f , v , val , a = 0;
 75 
 76     f = first[x] ;
 77 
 78     while( f!=-1 ){
 79         v = edge[f].v , val =edge[f].val ;
 80 
 81         if( dist[v]==dist[x]+1 && val>0 &&
 82            ( a = Dfs( v , min( len , val ) ) ) ){
 83                 edge[f].val -= a ;
 84                 edge[f+1].val += a ;
 85                 return a ;
 86         }
 87         f = edge[f].next ;
 88     }
 89 
 90     dist[x] = -1 ;
 91 
 92     return 0 ;
 93 }
 94 
 95 int dinic()
 96 {
 97     int ans = 0 ;
 98 
 99     while( bfs()==true ){
100         int k ; //cout<<" $ \n" ;
101         while( ( k=Dfs(s , 0x7fffffff) ) && (k!=0x7fffffff ) )
102             ans += k ;
103     }
104     return ans ;
105 }
106 
107 bool is_ok( int a , int b , int c , int dd ){
108     if( a==c && b==dd ) return false ;
109     int k = (int)fabs((double)(a-c)) + (int)fabs((double)(b-dd)) ;
110     if( k<=d_len ) return true ;
111     return false ;
112 }
113 
114 int main()
115 {
116     int T ;
117 
118     scanf("%d" , &T) ;
119 
120     for( int ii=1;ii<=T;ii++ )
121     {
122         init() ;
123         scanf("%d%d" , &n , &d_len) ;
124 
125         for( int i=0;i<n;i++ ) scanf("%s" , map1[i]) ;
126 
127         for( int i=0;i<n;i++ ) scanf("%s" , map2[i]) ;
128 
129         m = strlen( map1[0] ) ;
130 
131         s = 0 ; t = 1500 ;
132 
133         int num = 0 ;
134 
135         for( int i=0;i<n;i++ )
136         for( int j=0;j<m;j++ ){
137             int v = i*m+j+1 ;
138 
139             if( map2[i][j]=='L' ){
140                 Insert( s , v , 1 ) ,
141                 Insert( v , 400+v , 0x7fffffff ) ;
142                 ++num ;
143             }
144             if( map1[i][j]-'0' ){
145                 Insert( 400+v , 800+v , map1[i][j]-'0' ) ;
146                 if( i-d_len<0 || j-d_len<0 || i+d_len>=n || j+d_len>=m )
147                         
148                         Insert( 800+v , t , 0x7fffffff ) ;
149 
150                 int up , down , l , r  ;
151 
152                 up = max( 0 , i-d_len ) ;   down = min( n-1 , i+d_len ) ;
153                 l = max( 0 , j-d_len ) ;     r = min( m-1 , j+d_len ) ;
154                
155                 for( int k=up;k<=down;k++ )
156                     for( int c=l;c<=r;c++ ){
157                         if( ( (map1[k][c]-'0')>0 ) && is_ok( k , c , i , j ) )
158                             Insert( 800+v , 400+k*m+(c+1) , 0x7fffffff ) ;
159                     }
160             }
161         }
162 
163         int Max , ans ;
164         //cout<<endl<<endl;
165         //for( int i=1;i<=e_num;i++ )
166                  //cout<<edge[i].u<<" "<<edge[i].v<<" "<<edge[i].val<<" "<<edge[i].next<<endl;
167 
168         Max = dinic() ;
169 
170 
171         ans = num - Max ;
172 
173         printf("Case #%d: " , ii) ;
174 
175         if( ans==0 ) printf("no lizard was ") ;
176         else if( ans==1 )  printf("1 lizard was ") ;
177         else    printf("%d lizards were " , ans) ;
178 
179         printf("left behind.\n") ;
180     }
181 }

 

转载于:https://www.cnblogs.com/Crying-Smile/p/4456552.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值