Problem I. Hall of Fame
来源:ACM International Collegiate Programming Contest, Syrian Collegiate Programming Contest (2014) Syria, September, 23, 2014 CF链接Gym 100500I
ICPC World Finals 2014 was held in Russia, in Ekaterinburg from 21/06/2014 to 26/06/2014, hosted by Ural Federal University (UrFU). The opening ceremony was held on 23/06/2014 at 4:00 PM, in Cosmos Big Hall. During the ceremony a nice lady was singing the famous song "Hall of Fame". In case you don’t know the song here is its lyrics:(歌词在下图放大可查看)
Coach Fegla has invented a song effectiveness measurement methodology. This methodology in simple English means count the frequency of each character of the English letters [A-Z] in the given song (case insensitive). Get the top 5 characters with the highest frequencies, if 2 characters have the same frequency choose the one which is lexicographically larger. Sum up the indexes of these characters where the index of A is 0, index of B is 1, ..., index of of Z = 25. If this sum exceeds 62 print "Effective"otherwise print "Ineffective"without the quotes.
Input
The first line will be the number of test cases T. Each test case will consist of a series of words consisting only of upper or lower case English letters. Each test case ends with a line containing only "*"without the double quotes. Each word consists of a minimum of 1 letter and a max of 20 letters. The number of words in each test case will be a max of 20,000.
Output
For each test case print a single line containing: Case x: y x is the case number starting from 1. y is is the required answer either "Effective"or "Ineffective"without the quotes.
Examples
Fame.in:
2
You can be the greatest
*
You can be the best
You can be the King Kong banging on
your chest
*
Standard Output:
Case 1: Effective
Case 2: Ineffective
其实题目仔细分析就好,并不是很难,写代码的时候要细心。(题目意思就是:找出出现次数最多的那5个字母,如果出现次数相同则按字典序由大到小排序,A到Z分别指代0到25,最后将那5个字母代表的数字加起来,判断是否大于64,是则输出Effective,反之Ineffective。)
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
struct node
{
int data, x; // data用来存某个字母出现的次数,x来存编号代表相应字母(0->A/a,1->B/b...)
} b[27];
void qs(int l, int r);
int main()
{
int T;
scanf("%d", &T);
int i = 0, g = 1;
while(T)
{
getchar();
char a[20020][22];
scanf("%s", a[++i]); // 每次输入一个小子段并存下来
if(strcmp(a[i], "*") == 0) // 每当遇到*则判断,if语句中最后重置i为0,并且T--
{
memset(b, 0, sizeof(b)); // 将结构体数组初始化
for(int j = 1; j < i; j++)
{
int l = strlen(a[j]);
for(int k = 0; k < l; k++) // 判断A/a...Z/z并存下来相应编号
{
if(a[j][k] >= 'A' && a[j][k] <= 'Z')
{
b[a[j][k] - 'A'].data++;
b[a[j][k] - 'A'].x = a[j][k] - 'A';
}
else if(a[j][k] >= 'a' && a[j][k] <= 'z')//因为不分大小写,所以A与a使用同一下标
{
b[a[j][k] - 'a'].data++;
b[a[j][k] - 'a'].x = a[j][k] - 'a';
}
}
}
qs(0, 25); // 快排
for(i = 0; i < 25; i++)
{
for(int j = 0; j < 25 - i; j++)
{
if(b[j].data == b[j + 1].data && b[j].x < b[j + 1].x)
// 因为想要在快排中出现次数相同时直接判断字典序,但是失败了,所以这里写了一个冒泡只把出现次数相同的排一下字典序,很幸运没有超时^.^
{
struct node t = b[j];
b[j] = b[j + 1];
b[j + 1] = t;
}
}
}
int sum = 0;
for(i = 0; i < 5; i++)
{
sum += b[i].x; // 一切准备就绪,只需要将前5个字母代表的数值加起来就好
}
if(sum > 62) printf("Case %d: Effective\n", g++);
else printf("Case %d: Ineffective\n", g++);
i = 0;
T--; // 不要忘了组数减减,以及上边重置i为0
}
}
return 0;
}
void qs(int l, int r)
{
if(l >= r) return ;
int i = l, j = r;
struct node t = b[l];
while(i < j)
{ // 开始就是这里出问题了,注释掉的部分是失败的。。。但是不清楚为什么,看得出来的小伙伴欢迎下方评论指正
while(i < j && b[j].data <= t.data /*||(b[j].data == t.data && b[j].x < t.x))*/)
{
j--;
}
b[i] = b[j];
while(i < j && b[i].data >= t.data /*||(b[i].data == t.data && b[i].x > t.x))*/)
{
i++;
}
b[j] = b[i];
}
b[i] = t;
qs(l, i - 1);
qs(i + 1, r);
}