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("\n");
    }
    return 0;
}

时间: 2024-10-12 09:12:04

hdu 1557 权利指数 ( 二进制枚举子集) 解题心得的相关文章

HDU 1557 权利指数 状态压缩 暴力

HDU 1557 权利指数 状态压缩 暴力 ACM 题目地址:HDU 1557 权利指数 题意: 中文题,不解释. 分析: 枚举所有集合,计算集合中的和,判断集合里面的团体是否为关键团队. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * File: 1557.cpp * Create Date: 2014-06-28 14:47:58 * Descripton: brute force/ set */ #include <cstdio&g

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

【UVA】11464-Even Parity(二进制枚举子集)

枚举第一行的所有可能情况,之后根据上面行计算下面行(判断是否冲突),获得最终结果. 14058243 11464 Even Parity Accepted C++ 0.275 2014-08-18 05:14:15 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<stack> #inc

做实验 解题报告(二进制枚举子集)

题目描述 有一天,你实验室的老板给你布置的这样一个实验. 首先他拿出了两个长度为 n 的数列 a 和 b,其中每个 a i 以二进制表示一个集 合.例如数字 5 = (101) [2] 表示集合 {1, 3}.第 i 次实验会准备一个小盒子,里面装 着集合 a i 所有非空子集的纸条.老板要求你从中摸出一张纸条,如果满足你摸出的 纸条是 a i 的子集而不是 a i?b i ,a i?b i +1 ,...,a i?1 任意一个的子集,那么你就要被阿掉; 反之,你就逃过一劫. 令你和老板都没有想

(二进制枚举子集)买玩具

问题描述 蒜厂幼儿园有 n 个小朋友,每个小朋友都有自己想玩的玩具.身为幼儿园园长的你决定给幼儿园买一批玩具,由于经费有限,你只能买 m 个玩具.已知玩具商店一共卖 k 种玩具,编号为 1,2,3,…k,你让每个小朋友把想玩的玩具编号都写在了纸上.你希望满足尽可能多的小朋友的需求,请计算出最多同时能满足多少个小朋友的玩具需求. 输入格式 第一行,输入三个整数 n,m,k(1≤n≤100,1≤m≤k≤15),中间用空格分开. 接下来 n 行,第 i+1(0≤i< n) 行的第一个数字 ai代表第

二进制枚举子集

思路: 利用二进制的"开关"特性枚举: 具体为:假设给定集合A大小为n,则想象A = {a[0], a[1], ..., a[n-1]}的每个元素对应一个开关位(0或1),0表示不出现,1表示出现: 当每个元素的开关位的值确定时,就得到一个子集,因此共有2^n-1种情况(全0为空集,这里不考虑): 我们利用区间[1, 2^n-1],该区间上的每一个整数对应一个子集,对应方法是遍历该整数二进制表示的每一位: 若该位为1则相应子集中存在对应元素,否则不存在. 代码: #include &l

二进制枚举子集技巧

提供一个神奇的姿势 \(for(int \ i=sta;i;i=i-1\&sta)\) 稍微解释一下了,\(sta\)保存的0,1即为原来的需要求子集的集合,\(i\)即为遍历的子集 我们取的子集即是把当前集的元素取或不取,即\(sta\)的1取或不取 我们减去1,即是把最后一位的1变成0,最后一个1后面的0全变1,和原来的&一下,变的1全回去了,也把最后一位搞成0了 剩下的以此类推就差不多了 原文地址:https://www.cnblogs.com/ppprseter/p/9419344

HDU:1465不容易系列之一 解题心得

原题; Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好“一件”事情尚且不易,若想永远成功而总从不失败,那更是难上加难了,就像花钱总是比挣钱容易的道理一样. 话虽这样说,我还是要告诉大家,要想失败到一定程度也是不容易的.比如,我高中的时候,就有一个神奇的女生,在英语考试的时候,竟然把40个单项选择题全部做错了!大家都学过概率论,应该知道出现这种情况的概率,所以至今我都觉得这是一件神奇的事情.如果套用一句经典的评语,我们可以这样总结:一个人做错一道选

HDU 4911 Inversion - 疯狂的癫子 解题心得

原题: Description bobo has a sequence a 1,a 2,…,a n. He is allowed to swap two adjacent numbers for no more than k times. Find the minimum number of inversions after his swaps. Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n an