题目链接:UVA10785 - The Mad Numerologist
The Mad Numerologist
Numerology is a science that is used by many people to find out a mans personality, sole purpose of life, desires to experience etc. Some calculations of numerology are very complex, while others are quite simple. You can sit alone at home and do these easy calculations without taking any ones help. However in this problem you wont be asked to find the value of your name.
The Mad Numerologist |
![\epsfbox{p10785a.eps}](http://acm.bnu.edu.cn/v3/external/107/p10785a.jpg)
![\epsfbox{p10785b.eps}](http://acm.bnu.edu.cn/v3/external/107/p10785b.jpg)
- The name has a predefined length N.
- The vowel value and consonant value of the name must be kept minimum.
- To make the pronunciation of the name possible vowels and consonants are placed in alternate positions. Actually vowels are put in odd positions and consonants are put in even positions. The leftmost letter of a name has position 1; the position right to it is position 2 and so on.
- No consonants can be used in a name more than five times and no vowels can be used in a name more than twenty-one times
- Following the rules and limitations above the name must be kept lexicographically smallest. Please note that the numerologists first priority is to keep the vowel and consonant value minimum and then to make the name lexicographically smallest.
Input
First line of the input file contains an integer N ( 0 < N![$ \le$](http://acm.bnu.edu.cn/v3/external/107/10785img3.png)
Output
For each set of input produce one line of output. This line contains the serial of output followed by the name that the numerologist would suggest following the rules above. All letters in the output should be uppercase English letters.Sample Input
3 1 5 5
Sample Output
Case 1: A Case 2: AJAJA Case 3: AJAJA
题意
每个字母都有其价值
一个名字的元音价值是其元音字母的价值和,辅音价值是起辅音字母的价值和
这个名字有一个固定的长度N
先保证元音字母的价值和辅音字母的价值要最小,再保证名字要在字典序里面最小
第一个字符表示为1,元音字母在奇数位置,辅音在偶数位置
同一辅音最多出现5次,元音21次
分析
价值最小,首先得选取单个价值越小越好的,然后将其全部用完,再来考虑其他的字母。
字典序最小,那么就要对选取的字母进行较好的排序才能实现。
因此,首先需要做的是选字母,那些字母需要被选进来,以及需要的个数。
然后,按照字典序排列,将在字典序里面越前面的字母越早全部输出,再去排列其他的字母,注意元音与辅音的交叉排列。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct charc
{
char x;
int num;
};
bool cmp(charc a, charc b)
{
return a.x < b.x;
}
int main()
{
char vowels[] = "0AUEOI";
char cons[] = "0JSBKTCLDMVNWFXGPYHQZR";
int numv[7], numc[23];
int t, n, cas = 1;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
int vow = n/2;
if(n%2 != 0) vow++; //num of vowels
int cv = vow/21;
for(int i = 1; i <= cv; i++)
numv[i] = 21;
if(vow%21 != 0)
{
cv++;
numv[cv] = vow%21;
}
charc VW[7], CNN[24];
for(int i = 1; i <= cv; i++)
{
VW[i].x = vowels[i];
VW[i].num = numv[i];
}
int con = n/2; //num of cons
int cn = con/5;
for(int i = 1; i <= cn; i++)
numc[i] = 5;
if(con%5 != 0)
{
cn++;
numc[cn] = con%5;
}
for(int i = 1; i <= cn; i++)
{
CNN[i].x = cons[i];
CNN[i].num = numc[i];
}
sort(VW+1, VW+cv+1, cmp);
sort(CNN+1, CNN+cn+1, cmp);
int cnt1 = 0;
char ans1[150], ans2[150];
for(int i = 1; i <= cv; i++)
for(int j = 1; j <= VW[i].num; j++)
ans1[cnt1++] = VW[i].x;
int cnt2 = 0;
for(int i = 1; i <= cn; i++)
for(int j = 1; j <= CNN[i].num; j++)
ans2[cnt2++] = CNN[i].x;
cnt1 = cnt2 = 0;
printf("Case %d: ", cas++);
for(int i = 1; i <= n; i++)
{
if(i%2!=0)
printf("%c", ans1[cnt1++]);
else
printf("%c", ans2[cnt2++]);
}
printf("\n");
}
return 0;
}