PC/UVa:110108/10142
根据题目的过程模拟选举过程就可以了,但是也有几个注意的点:
- 得票为0的候选人出局
- 某个候选人票数大于50%时,选举胜利,此时只可能有一个人
- 当这一轮统计过后没有人出局时,也就是最小票数和最大票数相同时,即为平局的情况
每个候选人的票存在ticket
数组中,viOrder
表示每张选票的首选项,sCandidate
表示未出局的候选人。
循环中首先统计当前这一轮的首选项的结果,存储在mulmapCandidate2Voter
中。这是一个二元组组成的多重映射,第一维表示候选人编号,第二维表示此轮的选票号。使用多重映射可以很方便的得到每个候选人得票数,以及对应的选票号。
第二步是计算最大票数和最小票数,同时建立票数到候选人的映射mulmapTickets2Candidate
。这个映射中二元组的第一维表示此轮选票数目,第二维表示相应候选人编号。使用此映射可以从最小的票数找到对应的候选人,然后在使用上段中的映射就可以找到需要重新统计的选票。
第三步是计算是否有人胜出,或者是否为平局。
第四步是重新统计选票。使用mulmapTickets2Candidate
可以找到这一轮中出局的候选人,将其加入到sOuter
中,并从sCandidate
中去除。然后对于这一轮出局的每一个候选人,通过mulmapCandidate2Voter
找到对应的选票,更新每张选票的首选项(viOrder
),然后重新统计下一轮。
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <map>
#include <set>
using namespace std;
void vote()
{
int n = 0, total = 0;
cin >> n;
cin.get();
vector<string> vecstr(n, "");
vector<int> viOrder(1000, 0);
string strLine;
int ticket[1000][20] = { 0 };
set<int> sCandidate;
for (int i = 0; i < n; i++)
{
getline(cin, vecstr[i]);
sCandidate.insert(i);
}
while (getline(cin, strLine)){
if (strLine.empty()) break;
istringstream iss(strLine);
for (int i = 0; i < n; i++)
{
iss >> ticket[total][i];
ticket[total][i]--;
}
total++;
}
int candidate, voter, outer;
while (1){
int max = 0, get = 0, min = 1000;
multimap<int, int> mulmapCandidate2Voter;
multimap<int, int> mulmapTickets2Candidate;
set<int> sOuter;
//统计这一轮所有候选人的得票
for (voter = 0; voter < total; voter++)
{
if (viOrder[voter] == n) continue;
candidate = ticket[voter][viOrder[voter]];
mulmapCandidate2Voter.insert(pair<int, int>(candidate, voter));
}
//计算最高票和最低票数目,并建立从票数到候选人的多重映射
for (set<int>::iterator iter = sCandidate.begin(); iter != sCandidate.end(); iter++)
{
get = mulmapCandidate2Voter.count(*iter);
if (get > max) max = get;
if (get < min) min = get;
mulmapTickets2Candidate.insert(pair<int, int>(get, *iter));
}
//如果最高票数超过了50%则选举胜出
if (max * 2 > total){
cout << vecstr[mulmapTickets2Candidate.find(max)->second] << endl;
return;
}
else if (max == min){//平局
for (multimap<int, int>::iterator iter = mulmapTickets2Candidate.lower_bound(max);
iter != mulmapTickets2Candidate.upper_bound(max); iter++)
{
cout << vecstr[iter->second] << endl;
}
return;
}
//票数最低的候选人出局
for (multimap<int, int>::iterator iter = mulmapTickets2Candidate.lower_bound(min);
iter != mulmapTickets2Candidate.upper_bound(min); iter++)
{
outer = iter->second;
sOuter.insert(outer);
sCandidate.erase(outer);
}
//更新需要重新统计的选票的首选项
for (set<int>::iterator iter1 = sOuter.begin(); iter1 != sOuter.end(); iter1++)
{
outer = *iter1;
for (multimap<int, int>::iterator iter2 = mulmapCandidate2Voter.lower_bound(outer);
iter2 != mulmapCandidate2Voter.upper_bound(outer); iter2++)
{
voter = iter2->second;
while (++viOrder[voter] != n){
candidate = ticket[voter][viOrder[voter]];
if (sCandidate.find(candidate) != sCandidate.end()){
break;
}
}
}
}
}
}
int main()
{
int n = 0;
cin >> n;
cin.get();
cin.get();
for (int i = 0; i < n; i++)
{
vote();
if (i != n - 1) cout << endl;
}
}
/*
2
3
John Doe
Jane Smith
Jane Austen
1 2 3
2 1 3
2 3 1
1 2 3
3 1 2
5
A
B
C
D
E
4 1 3 2 5
1 4 3 5 2
5 4 2 1 3
5 1 4 2 3
2 3 1 5 4
*/