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[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 << 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[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;
}
深搜:
#include <iostream>
using namespace std;
int con[25], ans[25], total, n, a[25], key; //con存放a中元素编号
bool visited[25];
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[con[i]] <= total)
ans[con[i]]++;
return ;
}
for (int i = x + 1; i < n; i++)
{
con[times] = i;
dfs (i, sum+a[i], 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[i];
total /= 2;
memset (ans, 0, sizeof(ans));
for (key = 1; key <= n; key++) //枚举获胜联盟中团体个数
{
memset (visited, false, sizeof(visited));
visited[0] = true;
dfs (-1, 0, 0);
}
for (i = 0; i < n - 1; i++)
printf ("%d ", ans[i]);
printf ("%d\n", ans[n-1]);
}
return 0;
}
分享到:
相关推荐
子集(二进制序列枚举法)是一种解决数组子集问题的方法,它涉及到计算机科学中的位操作和组合数学。给定一个互不相同的整数数组 `nums`,任务是生成所有可能的子集,包括空集,并且不包含重复的子集。问题的关键...
【基于二进制作用模糊子集推理的单片机模糊控制】是一种将模糊逻辑理论与单片机技术相结合的方法,用于提升控制系统的智能化和实时性。单片机模糊控制器分为两类,一类是硬件实现的模糊单片机控制器,利用模糊逻辑...
总的来说,使用二进制排除不符合条件的n位数是一种巧妙的策略,它利用了二进制数的性质,使得在解决组合问题时能够有效地避免重复,并且提供了一种高效的方法来枚举所有可能的子集。在编程和算法设计中,这样的思维...
将6bit二进制转换为ASCII码,将ASCII码转换为6bit二进制
将二进制引入关联规则求解中,充分利用二进制操作方便、运算速度快、节省空间的优势。在求解事务项集真子集和支持度时,对事务数据库中相同事务只求解一次,并给出了真子集的具体求解算法。本算法一次扫描数据库可以...
在给出的文件列表中,“POJ1014-Dividing【多重背包+二进制优化】.cpp”和“POJ1014-Dividing【DFS】.cpp”很可能是两份不同的C++代码实现,分别展示了如何结合多重背包和二进制优化以及如何利用DFS来解决问题。...
- 而在状态压缩类动态规划中,通过将这些变量的状态进行二进制编码,可以使用一个整数来表示所有变量的状态组合。 - 这种编码方式被称为“状态压缩”。 2. **位操作**: - 状态压缩依赖于二进制下的位操作(如与...
在二进制特征选择中,每个候选特征子集都可以用一个二进制编码来表示,其中每一位对应一个特征是否被选中。以下是使用GA进行二进制特征选择的一般步骤: 编码:将特征选择问题转化为一个二进制编码的优化问题。假设...
C/C++语言编程安全子集
MATLAB代码会根据蜻蜓算法的规则,对这些二进制向量进行操作,逐步优化特征子集。这可能包括使用交叉验证来评估模型性能,以及设置停止条件,如达到预设的迭代次数或性能阈值。 在资源包中,可能包含以下文件: 1. ...
二分法二进制搜索 C ++ 二分法二进制搜索 C 构建宏 C 调试宏 C ++ 延迟宏,转到样式 C ++ 目录清单 C 小型YAML子集配置文件解析器 重击 双重bash /批处理文件 C 字节顺序转换 C 错误处理 C 紧...
本资源提供的是一种基于灰狼优化算法(Grey Wolf Optimization, GWO)实现的二进制特征选择方法,适用于解决特征冗余和不相关的问题。 灰狼算法是一种模拟自然界灰狼群捕食行为的优化算法,具有较强的全局搜索能力...
- 任意的八进制有限小数也一定是二进制有限小数,因为八进制是二进制的子集。 - 任意的十六进制有限小数也是十进制有限小数,因为十六进制是二进制的子集。 10. 二进制数转换: - 1111111111转换为十进制是1023...
在IT领域,编译器是计算机科学中的一个重要组成部分,它将高级编程语言转换为机器可理解的二进制代码。本项目聚焦于PASCAL语言的一个子集——PL/0的编译器设计与实现。PASCAL是一种结构化编程语言,而PL/0是其简化...
对于这个问题,我们可以使用状态压缩技术来表示每一个可能的状态,每个状态可以看作是一个二进制数,其中的每一位对应图中的一个顶点,如果该位为1,则表示该顶点已被访问过;如果为0,则表示未被访问。 通过这种...
在这个项目中,我们将深入探讨如何利用原子搜索算法进行二进制特征选择,并结合MATLAB代码进行实践。 一、特征选择的重要性 特征选择对机器学习模型的影响显著,主要体现在以下几个方面: 1. **降低计算复杂度**:...
6. **16进制到二进制再到10进制**:同样,16进制浮点数先转换为二进制,然后根据IEEE 754的规则解析二进制流,包括符号位、指数位和尾数位,最后计算出10进制值。 7. **转换工具的使用**:在提供的“浮点数转换工具...
- **十六进制**:十六进制是二进制的一种压缩形式,用两位十六进制数可以表示一个字节的数据。对于ASCII编码,只需关注前两位十六进制数即可。 #### 3. ASCII编码表详解 ASCII编码表包含了所有128个标准字符的编码...
常用的方法是利用二进制位来表示不同的状态,比如在一个有n个元素的集合中,可以用n位的二进制数来表示不同的子集,每一位代表集合中的一个元素是否存在。 #### 2. 复杂度分析 对于状态压缩DP,状态的数量通常是...