UVa 10142 - Australian Voting

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=29&page=show_problem&problem=1083

题意:这个题刘汝佳在挑战编程上翻译的让我各种费解,后来看了这个翻译才明白:http://hi.baidu.com/knowledgetime/blog/item/6017ea04bb35cfc37a894779.html

摘抄如下:

UVa 10142 - Australian Voting 
澳大利亚在选举的时候,他们要求投票者在选票上将候选人做一个排名的动作。一开始先计算所有选票中的「第一选择」,如果有某位候选人在此时获得过半(50%)的选票,那么这位候选人立即当选。如果没有任何候选人获得过半的选票,那么票数最少的所有候选人将被排除当选资格,那些原本选择这些候选人的选票,则依照顺位将票投给下一个仍未出局的候选人。这个流程不断的重复(每一次的计票,票数最少的那些候选人都被排除当选),

或者是所有剩下的候选人得票数相同才停止 

Input 

输入的第一列和第一笔测试资料之间,以及连续两笔测试资料之间都包含了一列空白。 

输入的第一列有一个整数n (n<=20)代表候选人的个数。接下来的n列每一列依序表示了候选人的名字。这些名字可能长达80个可印出的字元。 

然后会有至多1000列,每一列包含了一张选票的内容。每一张选票都包含了一个1~n的排列,第一个数代表这张选票上的「第一选择」,第二个数字代表第二顺位…以此类推。 

Output 

对于任两笔连续的测试资料中间请输出一列空白。 

对每一组测试资料输出赢得选举的候选人名字,或是同时打成平手的所有候选人名字。
 

Sample Input 



John Doe 
Jane Smith 
Sirhan Sirhan 
1 2 3 
2 1 3 
2 3 1 
1 2 3 
3 1 2 


Sample Output 
John Doe 

这个题只要明确了题意剩下的就比较简单了。

  1 #include <cstdio>

  2 #include <cstring>

  3 

  4 const int MAXN = 1010;

  5 

  6 struct vote      //每张选票

  7 {

  8     int who[25];

  9 };

 10 

 11 vote V[MAXN];           //每张选票

 12 char name[25][100];     //候选人名单

 13 bool vis[25];           //记录该候选人是否出局

 14 int count[25];          //每个候选人的票数

 15 int n, k;

 16 

 17 void Solve()

 18 {

 19     memset( vis, true, sizeof(vis) );

 20     int left = 0;

 21 

 22     bool flag = true;             //是否继续统计票数

 23     bool getans = false;          //是否平局

 24 

 25     while ( flag )

 26     {

 27         memset( count, 0, sizeof(count) );

 28         for ( int i = 0; i < k; i++ )

 29         {

 30             for ( int j = 0; j < n; j++ )

 31             {

 32                 int& peo = V[i].who[j];

 33                 if ( vis[ peo - 1 ] )

 34                 {

 35                     ++count[ peo - 1 ];

 36                     break;

 37                 }

 38             }

 39         }

 40 

 41         //   for ( int i = 0; i < n; i++ ) printf( "%d ", count[i] );

 42         //         putchar('\n');

 43 

 44         for ( int i = 0; i < n; i++ )

 45         {

 46             if ( count[i] > k / 2 )          //如果有人票数过半

 47             {

 48                 puts( name[i] );

 49                 flag = false;

 50                 getans = true;

 51                 break;

 52             }

 53         }

 54         if ( !flag ) break;                  //如果有人票数过半,则输出结果,统计结束

 55 

 56         flag = false;

 57         int old;

 58         int i;

 59         left = 0;

 60         for ( i = 0; i < n; i++ )

 61             if ( vis[i] )

 62             {

 63                 old = count[i];

 64                 ++left;

 65                 break;

 66             }

 67         for ( ++i; i < n; i++ )              //判断是否剩下的人票数相同

 68             if ( vis[i] )

 69             {

 70                 ++left;

 71                 if ( count[i] != old )

 72                 {

 73                     flag = true;

 74                     break;

 75                 }

 76             }

 77         if ( !flag || left == 1 ) break;     //如果平局,或者只剩一个候选人,输出结果,退出

 78 

 79         int min = 2000;

 80         for ( int i = 0; i < n; i++ )

 81             if ( vis[i] )                  //少了这个vis,TLE了三遍,进死循环了

 82                 if ( count[i] < min ) min = count[i];

 83 

 84         for ( int i = 0; i < n; i++ )      //每次票数最少的人出局

 85             if ( vis[i] )

 86                 if ( count[i] == min )  vis[i] = false;

 87     }

 88 

 89     if ( !getans )                         //如果平局,输出所有并列的候选人

 90     {

 91         for ( int i = 0; i < n; i++ )

 92             if ( vis[i] ) puts( name[i] );

 93     }

 94 

 95     return;

 96 }

 97 

 98 int main()

 99 {

100     //  freopen( "s.txt", "w", stdout );

101     int T;

102     char str[100];

103     scanf( "%d", &T );

104     while ( T-- )

105     {

106         scanf( "%d", &n );

107         getchar();

108         for ( int i = 0; i < n; i++ )                    //读入候选人名单

109             gets( name[i] );

110 

111         k = 0;

112         while ( gets( str ) != NULL && str[0] != '\0' )  //读入选票

113         {

114             int len = strlen(str);

115             int j = 0;

116             for ( int i = 0; i < len; i++ )

117             {

118                 if ( str[i] != ' ' )

119                 {

120                     int cnt = 0;

121                     while ( str[i] != ' ' && str[i] != '\0' )

122                         cnt = cnt * 10 + ( str[i++] - '0' );

123                     V[k].who[j++] = cnt;

124                 }

125             }

126             ++k;

127         }

128 

129         Solve();

130 

131         if (T) putchar('\n');

132     }

133     return 0;

134 }

你可能感兴趣的:(uva)