基德KID.1412 发表于 2013-1-26 12:36:08

【二进制状态压缩+子集枚举/新增深搜】HDU 1557 权利指数

http://acm.hdu.edu.cn/showproblem.php?pid=1557


Problem 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

#include <iostream>using namespace std;int main(){int t, n, a, i, key, k, total, ans;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;total /= 2;    //总票数的一半【写成total = (total+1)/2 会错……】//枚举子集【1】~【2的n次方-1】int maxs = 1 << n;for (i = 1; i < maxs; i++){k = 0;int tp = i, j = 0, sum = 0;while (tp){if (tp & 1)//tp的二进制从左往右数第j位是1,则认为a入了集合key = j, sum += a;//记住入了集合的a的元素编号j,并累加票数tp >>= 1;    //tp的二进制往右移动,即消去二进制最后一位j++;}if (sum > total)    //如果团体的票数超过总票数的一半for (j = 0; j < k; j++)if (sum - a] <= total)ans]++;//如果没了a]就不行,则编号为key的元素为“关键加入者”,该元素权利指数+1}printf ("%d", ans);for (i = 1; i < n; i++)printf (" %d", ans);printf ("\n");}return 0;}

深搜:
#include <iostream>using namespace std;int con, ans, total, n, a, key;    //con存放a中元素编号bool visited;void dfs (int x, int sum, int times)//x是元素编号,sum是临时和,times是con中元素个数{    if (times == key)    {      if (sum > total)            for (int i = 0; i < times; i++)                if (sum - a] <= total)                  ans]++;      return ;    }    for (int i = x + 1; i < n; i++)    {      con = i;      dfs (i, sum+a, times+1);    }}int main(){    int t, i;    scanf ("%d", &t);    while (t--)    {      scanf ("%d", &n);      total = 0;      for (i = 0; i < n; i++)            scanf ("%d", a+i), total += a;      total /= 2;      memset (ans, 0, sizeof(ans));      for (key = 1; key <= n; key++)    //枚举获胜联盟中团体个数      {            memset (visited, false, sizeof(visited));            visited = true;            dfs (-1, 0, 0);      }      for (i = 0; i < n - 1; i++)            printf ("%d ", ans);      printf ("%d\n", ans);    }    return 0;}
页: [1]
查看完整版本: 【二进制状态压缩+子集枚举/新增深搜】HDU 1557 权利指数