zoukankan      html  css  js  c++  java
  • hdu 1557 权利指数 ( 二进制枚举子集) 解题心得

    原题:

    Description

    在选举问题中,总共有n个小团体,每个小团体拥有一定数量的选票数。如果其中m个小团体的票数和超过总票数的一半,则此组合为“获胜联盟”。n个团体可形成若干个获胜联盟。一个小团体要成为一个“关键加入者”的条件是:在其所在的获胜联盟中,如果缺少了这个小团体的加入,则此联盟不能成为获胜联盟。一个小团体的权利指数是指:一个小团体在所有获胜联盟中成为“关键加入者”的次数。请你计算每个小团体的权利指数。
     

    Input

    输入数据的第一行为一个正整数T,表示有T组测试数据。每一组测试数据的第一行为一个正整数n(0<n<=20)。第二行有n个正整数,分别表示1到n号小团体的票数。
     

    Output

    对每组测试数据,在同一个行按顺序输出1到n号小团体的权利指数。
     

    Sample Input

    2 1 10 7 5 7 4 8 6 7 5
     

    Sample Output

    1 16 22 16 24 20 22 16
     
     分析:n位二进制数,每个都有不同状态1,0,所以可以表示2^n种不同情况,具体实现方法是 ,tp&1   的结果为tp的最后一位是不是1,是1返回真,
    否则返回假,之后再每次将tp>>1.这样就可以逐位判断了 
     
     
    我的代码:
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int t, n, a[25], i, key[25], k, total, ans[25];
        scanf("%d", &t);
        while (t--)
        {
            memset(ans, 0, sizeof(ans));
            total = 0;
            scanf("%d", &n);
            for (i = 0; i < n; i++)
                scanf("%d", a + i), total += a[i];
            total /= 2;    //总票数的一半【写成total = (total+1)/2 会错……】
            //枚举子集【1】~【2的n次方-1】
            int maxs = 1 << 3;
            cout <<"maxs="<< maxs << endl;
            int flag = 0;
            for (i = 1; i < maxs; i++)
            {
                cout << flag++ << endl;
                k = 0;
                int tp = i, j = 0, sum = 0;
                while (tp)
                {
                    //cout <<"tp="<<tp<<"       "<< (tp & 1) << endl;
                    if (tp & 1)//tp的二进制从左往右数第j位是1,则认为a[j]入了集合
                        key[k++] = j, sum += a[j];
                    //记住入了集合的a的元素编号j,并累加票数
                    tp >>= 1;    //tp的二进制往右移动,即消去二进制最后一位
                    j++;
                }
                if (sum > total)    //如果团体的票数超过总票数的一半
                for (j = 0; j < k; j++)
                if (sum - a[key[j]] <= total)
                    ans[key[j]]++;
                //如果没了a[key[j]]就不行,则编号为key[j]的元素为“关键加入者”,该元素权利指数+1
            }
                printf("%d", ans[0]);
            for (i = 1; i < n; i++)
                printf(" %d", ans[i]);
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    2、ansilbe常用模块详解及inventory介绍
    1、Ansible简介及简单安装、使用
    dhcp、tftp及pxe简介
    php-fpm常见错误
    php之编译安装
    nginx之常见错误
    ssh之秘钥登陆
    MySQL之主从复制
    Python之虚拟环境
    php调试工具之firePHP
  • 原文地址:https://www.cnblogs.com/shawn-ji/p/4696658.html
Copyright © 2011-2022 走看看