模拟类。本来是挺简单的,但是有几个地方没想明白,所以Wrong answer了好久。跟丫拼了,写了个测试用例生成程序,生成了一堆用例,逐一检验,终于AC了。至此《挑战编程-程序设计竞赛训练手册》第一章习题(UVa中文翻译)解答完毕,等全部AC了再做个索引目录吧。
Q10142: Australian Voting
澳大利亚在选举的时候,他们要求投票者在选票上将候选人做一个排名的动作。一开始先计算所有选票中的“第一选择”,如果有某位候选人在此时获得过半(50%)的选票,那么这位候选人立即当选。如果没有任何候选人获得过半的选票,那么票数最少的所有候选人将被排除当选资格,那些原本选择这些候选人的选票,则依照顺位将票投给下一个仍未出局的候选人。这个流程不断的重复(每一次的计票,票数最少的那些候选人都被排除当选),直到有一位候选人得到超过50%的选票或者是所有剩下的候选人得票数相同才停止。
Input
输入的第一列和第一笔测试资料之间,以及连续两笔测试资料之间都包含了一列空白。
输入的第一列有一个整数 n (n<=20)代表候选人的个数。接下来的 n列每一列依序表示了候选人的名字。这些名字可能长达80个可印出的字元。
然后会有至多1000列,每一列包含了一张选票的内容。每一张选票都包含了一个1~n的排列,第一个数代表这张选票上的“第一选择”,第二个数字代表第二顺位…以此类推。
Output
对于任两笔连续的测试资料中间请输出一列空白。
对每一组测试资料输出赢得选举的候选人名字,或是同时打成平手的所有候选人名字。
| Sample Input | Sample Output |
1 3 John Doe Jane Smith Sirhan Sirhan 1 2 3 2 1 3 2 3 1 1 2 3 3 1 2 |
John Doe |
简体中文由Lucky貓的 UVA(ACM)園地转换。
我的解法,很长很罗嗦,老实说,这是我写过的最丑的代码。
12880877 10142 Australian Voting Accepted C++ 0.666 2013-12-22 16:55:32
#ifndef ONLINE_JUDGE
#pragma warning(disable : 4996)
#endif
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
struct Person
{
string name;
int votes;
int index;
};
struct Ticket
{
int vote[20];
};
bool compare_person(const Person& p1, const Person& p2)
{
return p1.votes > p2.votes;
}
void dump_list(const vector<Person>& list_person)
{
return;
for (vector<Person>::const_iterator it = list_person.begin(); it != list_person.end(); ++it)
{
cout << it->name << " " << it->votes << endl;
}
cout << "-----------" << endl;
}
void vote_for(vector<Person>& list_person, const int& index)
{
for (vector<Person>::iterator it = list_person.begin(); it != list_person.end(); ++it)
{
if (it->index == index)
{
++(it->votes);
}
}
}
bool is_live(vector<Person>& list_person, const int& index)
{
for (vector<Person>::iterator it = list_person.begin(); it != list_person.end(); ++it)
{
if (it->index == index)
{
return true;
}
}
return false;
}
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int n = 0;
cin >> n;
while (n--)
{
int original_person_count = 0;
cin >> original_person_count;
if (original_person_count == 0)
{
continue;
}
cin.ignore();
vector<Person> list_person(original_person_count);
vector<Ticket> list_tickets;
string line;
for (int i = 0; i < original_person_count; ++i)
{
getline(cin, line);
Person p;
p.name = line;
p.votes = 0;
p.index = i;
/*cout << p.name << endl;*/
list_person[i] = p;
}
while (getline(cin, line) && line.length() > 0)
{
istringstream stream(line);
Ticket t;
for (int i = 0; i < original_person_count; ++i)
{
stream >> t.vote[i];
/*cout << t.vote[i];*/
--t.vote[i];
}
list_tickets.push_back(t);
/*cout << endl;*/
}
int size = list_tickets.size();
for (int i = 0; i < size; ++i)
{
Ticket t = list_tickets[i];
vote_for(list_person, t.vote[0]);
}
dump_list(list_person);
while (true)
{
int max_vote = 0, min_vote = list_person.begin()->votes;
for (vector<Person>::const_iterator it = list_person.begin(); it != list_person.end(); ++it)
{
if (it->votes > max_vote)
{
max_vote = it->votes;
}
else if (it->votes < min_vote)
{
min_vote = it->votes;
}
}
if (max_vote * 2 > list_tickets.size())
{
// 得票过半,结束
if (list_person.size() > 1)
{
for (vector<Person>::iterator it = list_person.begin(); it != list_person.end();)
{
if (it->votes < max_vote)
{
it = list_person.erase(it);
}
else
{
++it;
}
}
}
dump_list(list_person);
break;
}
else if (max_vote == min_vote)
{
// 所有人得票一样,结束
dump_list(list_person);
break;
}
else
{
// 最后那几个个人出局
// 出局的人的id
vector<int> out_list;
for (vector<Person>::iterator it = list_person.begin(); it != list_person.end();)
{
if (it->votes == min_vote)
{
out_list.push_back(it->index);
it = list_person.erase(it);
}
else
{
++it;
}
}
// 每出局一个人,原来投给他的票必须重新计算
for (vector<int>::const_iterator it_out = out_list.begin(); it_out != out_list.end(); ++it_out)
{
for (vector<Ticket>::iterator it = list_tickets.begin(); it != list_tickets.end(); ++it)
{
Ticket t = *it;
for (int position = 0; position < original_person_count; ++position)
{
if (is_live(list_person, t.vote[position]))
{
break;
}
if (t.vote[position] == *it_out)
{
for (position = position + 1; position < original_person_count; ++position)
{
if (is_live(list_person, t.vote[position]))
{
vote_for(list_person, t.vote[position]);
// cout << "投给" << *it_out + 1 << "的票" << t.vote[0] + 1 << " " << t.vote[1] + 1 << " " << t.vote[2] + 1 << " " << t.vote[3] + 1 << " "
// << "要重投给" << t.vote[position] + 1 << endl;
dump_list(list_person);
break;
}
}
break;
}
else if (find(out_list.begin(), out_list.end(), t.vote[position]) != out_list.end())
{
break;
}
}
}
}
}
}
for (vector<Person>::const_iterator it = list_person.begin(); it != list_person.end(); ++it)
{
cout << it->name << endl;
}
if (n && list_person.size())
{
cout << endl;
}
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
///////////////////////////End Sub//////////////////////////////////
码农场