标签:
有一个方格 , 方格里面的每个格子要么是无底洞 , 要么有一根竖着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 }
标签:
原文地址:http://www.cnblogs.com/Crying-Smile/p/4456552.html