选举问题
题目详情:
在许多选举的问题上,并不是每个人都是一张票的,很多时候会由于每个人的权利不同导致每个人的话事权也不一样(可认为所拥有的票数)假设有选举人V1,V2...Vk,他们所拥有的票数分别为w1,w2...wk;并设优势联盟为所有选举人的一个子集且他们的总票数超过一半。而Vi拥有的权利指数为在有他的所有优势联盟中,他退出便能使优势联盟变为劣势联盟的次数。若Vi一个人的票数便已经超过一半,则称他为独裁者,我们认为这种选举是不公平的。现在,我们就是要看一个选举系统是否存在独裁,若不存在,求出每个选举人的权利指数。
输入:第一行为T,表示有T个案例!每个案例第一行为k,表示有k个选举人(1<k<=20),第二行为k个数,表示每个选举人所拥有的票数。
输出:若存在独裁,则输出"It's unfair!",否则输出每个选举人的权利指数。
答题说明:
输入案例:
2
2
5 1
5
3 4 5 6 7
输出案例:
It's unfair!
4 4 4 8 8
状态压缩+模拟;i&-i是取i的最后一位1(补码)。
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int K=21;
int bt[K+1],ans[K];
int num[1<<K],w[1<<K];
int main(){
bt[0]=1;
for(int i=1;i<=K;i++)
bt[i]=bt[i-1]*2;
int tt,n,cases=0;
cin>>tt;
while(cases++<tt){
cin>>n;
int sum=0;
for(int i=0;i<n;i++){
cin>>w[bt[i]];
sum+=w[bt[i]];
}
sum=sum/2;//大于一半
for(int i=0;i<n;i++){
if(w[bt[i]]>sum){
printf("It's unfair!\n");
goto next;
}
}
num[0]=0;
for(int i=1;i<bt[n];i++){
int last=(i&-i);
num[i]=num[i-last]+w[last];
}
int goal=0;
memset(ans,0,sizeof ans);
for(int i=1;i<bt[n];i++){
if(num[i]>sum)//优势状态i
for(int j=0;j<n;j++)
if(i&bt[j])//j在集合中
if(num[i]-w[bt[j]]<=sum)
ans[j]++;
}
for(int i=0;i<n-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n-1]);
next: ;
}
return 0;
}