HDU 5046 Airport ( Dancing Links 重复覆盖 )

来源:互联网 发布:jackson json 官网 编辑:程序博客网 时间:2024/06/10 05:01

今年上海网络赛的一道题目 , 跟 HDU 2295 如出一辙 , 就是距离的计算一个是欧几里得距离 , 一个是曼哈顿距离

学完DLX感觉这题好水 ,就是一个裸的重复覆盖

注意下别溢出就行了


#include <stdio.h>    #include <string.h>    #include <algorithm>    #include <vector>    #include <math.h>  #include <stdlib.h>using namespace std;    const int maxn = 60 + 10 ;    const int maxr = 60 + 10 ;    const int maxnode = 60 * 60 + maxr + 10 ;    #define FOR( i , A , s ) for( int i = A[s] ; i != s ; i = A[i] )     struct DLX{    // maxn 列数 , maxnode 总节点数 , maxr 行数    int n , sz ;    int S[maxn] ;     int row[maxnode] , col[maxnode] ;    int L[maxnode] , R[maxnode] , U[maxnode] , D[maxnode] ;    int H[maxr] ;    int ansd , ans[maxr] ;    void init( int N ) {    n = N ;    // 第一行的虚拟结点    for( int i = 0 ; i <= n ; i ++ ) {    U[i] = D[i] = i ;    L[i] = i - 1 ;     R[i] = i + 1 ;    }    R[n] = 0 ; L[0] = n ;    sz = n + 1 ;    // 每一列的个数    memset( S , 0 , sizeof(S) ) ;    // H[i] = -1 表示这一行还没有 1     // 否则表示第一个 1 的 sz 是多少    memset( H , -1 , sizeof(H)) ;    }    // 在第r行第c列添加一个1    void Link( int r , int c ) {    row[sz] = r ;    col[sz] = c ;    S[c] ++ ;    D[sz] = c ; U[sz] = U[c] ;    D[U[c]] = sz ; U[c] = sz ;    if( H[r] < 0 ) { H[r] = L[sz] = R[sz] = sz ; }    else{    R[sz] = H[r] ;    L[sz] = L[H[r]] ;    R[L[sz]] = sz ;    L[R[sz]] = sz ;    }    sz ++ ;    }    // 删除 第 c 列    void remove ( int c ) {    FOR( i , D , c ) {  L[R[i]] = L[i] ;  R[L[i]] = R[i] ;  }  }    // 恢复第 c 列    void restore( int c ) {   FOR( i , D , c ) {  L[R[i]] = R[L[i]] = i ;  }  }    bool vis[maxn] ;  int f() {  int ans = 0 ;  FOR( i , R , 0 ) vis[i] = true ;  FOR( i , R , 0 ) {  if( vis[i] ) {  vis[i] = false ;  ans ++ ;  FOR( j , D , i )  FOR( k , R , j )  vis[col[k]] = false ;  }  }  return ans ;  }  bool dfs( int d ) {  // 剪枝  if( d + f() > best ) return false ;  // R[0] = 0 表示找到一个可行解  if( R[0] == 0 ) return d <= best ;    // 找到 s 最小的列 , 加快搜索的速度    int c = R[0] ;    FOR( i , R , 0 )  if( S[i] < S[c] ) c = i ;  FOR( i , D , c ) {    remove(i);    FOR( j , R , i ) remove( j );    if (dfs(d + 1))   return true ;    FOR( j , R , i ) restore( j ) ;    restore( i ) ;    }    return false ;  }    bool solve( int k ) {    best = k ;  return dfs(0) ;  }    int best ;  } dlx ;    int n , m , k ;  __int64 ABS( __int64 x ) {return x  < 0 ? -x : x ;}struct Point{  __int64 x , y ;  void get(){  scanf( "%I64d%I64d" , &x , &y ) ;  }  friend __int64 dist ( const Point &a  , const Point & b ) {  return ABS( a.x - b.x ) + ABS ( a.y - b.y ) ;}  };  Point city[65] ;  __int64 dis[60*60+10] ;int lisanhua( int Index ) {int cnt = 1 ;for( int i = 1 ; i < Index ; i ++ ) {if( dis[i] != dis[i-1] ) dis[cnt++] = dis[i] ;}return cnt - 1 ;}int main(){  int cas ;  int casn = 1 ;scanf( "%d" , &cas ) ;  while( cas -- ) {  scanf( "%d%d" , &n, &k ) ;  for( int i = 1 ; i <= n ; i ++ ) {  city[i].get() ;  } int Index = 0 ;for( int i = 1 ; i <= n ; i ++ ) {for( int j = i ; j <= n ; j ++ ) {dis[Index++] = dist( city[i] , city[j] ) ;}}sort( dis , dis + Index ) ;Index = lisanhua( Index ) ;__int64 l = 0 , r = Index ;  __int64 mid ;  while( l < r ) {  mid = ( l + r ) / 2 ;  dlx.init( n ) ;  for( int i = 1 ; i <= n ; i ++ ) {  for( int j = 1 ; j <= n ; j ++ ) {  if( dist( city[i] , city[j] ) <= dis[mid] ) {  dlx.Link( i , j ) ;  }  }  }  if( dlx.solve( k ) ) {  r = mid ;  }else{  l = mid + 1 ;  }  }  printf( "Case #%d: %I64d\n" , casn ++ , dis[l] ) ;  }  return 0 ;  }  


2 0
原创粉丝点击