糯米

TI DaVinci, gstreamer, ffmpeg
随笔 - 167, 文章 - 0, 评论 - 47, 引用 - 0
数据加载中……

POJ 1081 You Who? 枚举+位运算

题目大意:
有一群学生,其中有些人是相互认识的。将学生分为两组,这两组的人数最大只能相差1。
定义一个学生的“孤独指数”为组内他不认识的人的人数。
问怎么分组,才能使这两组中最孤独学生的“孤独指数”最小。

思路:
想不到算法,于是看Discuss。原来是用枚举。。
暴力枚举每一种分组情况,求该情况下“最孤独学生的孤独指数”。
据说数据很弱,N最大才是4,囧。所以0msAC。

#include <stdio.h>

unsigned __int64 map[
64];
int N;
int bit_cnt[256];

__inline 
int calc_cnt(unsigned __int64 val)
{
    
return bit_cnt[((char *)&val)[0]] + 
           bit_cnt[((
char *)&val)[1]] + 
           bit_cnt[((
char *)&val)[2]] + 
           bit_cnt[((
char *)&val)[3]] + 
           bit_cnt[((
char *)&val)[4]] + 
           bit_cnt[((
char *)&val)[5]] + 
           bit_cnt[((
char *)&val)[6]] + 
           bit_cnt[((
char *)&val)[7]];
}


__inline 
int min(int a, int b)
{
    
return a < b ? a : b;
}


__inline 
int max(int a, int b)
{
    
return a < b ? b : a;
}


int main()
{
    
int i, j, k, l, r, arr[64], min_val;
    unsigned __int64 mask;

    freopen(
"e:\\test\\in.txt""r", stdin);

    
for (i = 0; i < 256; i++{
        k 
= 0;
        
for (j = i; j; j &= j - 1)
            k
++;
        bit_cnt[i] 
= k;
    }


    
while (scanf("%d%d"&j, &k) != EOF) {
        
while (k--{
            scanf(
"%d"&i);
            map[j] 
|= (unsigned __int64)1 << i;
        }

        
if (j > N)
            N 
= j;
    }

    
for (i = 1; i <= N; i++)
        map[i] 
|= (unsigned __int64)1 << i;

    min_val 
= N;
    
for (i = 1; i <= N/2; i++)
        arr[i] 
= i;
    
while (1{
        mask 
= 0;
        
for (i = 1; i <= N/2; i++)
            mask 
|= (unsigned __int64)1 << arr[i];
        l 
= r = N;
        
for (i = 1; i <= N; i++{
            
if (mask & ((unsigned __int64)1 << i)) 
                l 
= min(calc_cnt(map[i] & mask), l);
            
else
                r 
= min(calc_cnt(map[i] & ~mask), r);
        }

        i 
= max(N/2 - l, N - N/2 - r);
        
if (i < min_val)
            min_val 
= i;
        
for (i = N/2; i >= 1 && arr[i] == N + i - N/2; i--);
        
if (!i)
            
break;
        arr[i]
++;
        
for (j = 1; j + i <= N/2; j++)
            arr[j 
+ i] = arr[i] + j;
    }

    printf(
"%d\n", min_val);
    
    
return 0;
}



 

posted on 2010-02-13 01:48 糯米 阅读(711) 评论(0)  编辑 收藏 引用 所属分类: POJ


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理