• HDU 5046 Airport ( Dancing Links 反复覆盖 )


    今年上海网络赛的一道题目 , 跟 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
    " , casn ++ , dis[l] ) ;  
    	}  
    	return 0 ;  
    }  


  • 相关阅读:
    vue简单的富文本实现(亲测可以)
    做手机兼容性看友盟手机统计
    压测并发数上不去的原因分析(泽嵩大佬说的)
    跨域问题解决
    jmeter压力测试报Address already in use: connect错误
    选择器(可搜索)+气泡提示组件
    2020
    Redis集群搭建采坑总结
    echarts自定义背景图片
    百度ECharts地图Json数据在线下载(geoJson)
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5322709.html
Copyright © 2020-2023  润新知