题意:
大师起名, 要求:
1. 命字里元音和辅音的和最小.
2. 命字里元音都出现在奇数位, 辅音都出现在偶数位(从左往右, 最左边是 1, 依次累加).
3. 每个辅音最多能出现5次, 每个元音最多出现21次.
4. 在满足以上规则的情况下, 要求名字的字典序最小.
注: 看题时理解错题意, 想成要求元音与辅音的差最小, 结果想成动态规划问题, 纠结了一个晚上, 毫无思路, 最后还是看了别人翻译的题目才做出来的.
思路:
1. 根据输入的名字长度N, 算出需要几个元音和几个辅音.
2. 按元音/辅音代表的值, 从小到大取, 当单个元音/辅音的数量大于5/21时, 就开始取下一个元音/辅音, 直至取到需要的数量为止.
3. 把取到的元音和辅音分别按字典序由小到大进行排序.
4. 把元音和辅音交替输出, 即为所求结果.
要点:
1. 使用 sort 进行排序.
2. 不一定每次都使用 map, 像本题中, 上来的本能直觉就是按照 755 一样进行 map 映射, 其实没必要; 进一步思考可知, 每个元音/辅音所代表的是 2 还是 3 还是 5 根本没有关系, 只需要它们的排列顺序是按照它们的值/字典序从小到大进行排列的即可; 根据以上分析, 可以直接使用数组把 AUEOI, JSBKTCLDMVNWFXGPYHQZR 等存起来, 而无需用 map 来存.
本文最后的第一个解法更狠, 直接把210位长度时的最终解法列出来, 每次输入名字长度时, 就直接取就可以了; 解法是好解法, 但我不喜欢这样的手动暴力解法.
题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=1726
代码:
# include <iostream> # include <string> # include <cstdio> # include <cstring> # include <vector> # include <algorithm> # include <cctype> # include <iterator> # include <assert.h> using namespace std; // 要求的是 元音 和 铺音 的 value 分别最小,不是取它们各自和, // 然后算它们的差最小 // 好好的问题,因为读题错误,给复杂了无数倍... // 只要保证 value 小的在前面,同样 value 的时候,字母小的在前面即可 // 不一定死板的按图中给出的结构,设几个 map,或者几个 vector const char VOVEL[] = "AUEOI"; const char CONSONANT[] = "JSBKTCLDMVNWFXGPYHQZR"; const int V_TIME = 21; // 每个元音可以出现的次数 const int C_TIME = 5; // 每个辅音可以出现的次数 int main(int argc, char const *argv[]) { #ifndef ONLINE_JUDGE freopen("10785_i.txt", "r", stdin); freopen("10785_o.txt", "w", stdout); #endif int numSet = 0; cin >> numSet; for (int i=0; i<numSet; i++) { printf("Case %d: ", i+1); int lengthName; cin >> lengthName; int numVovel = (lengthName + 1) / 2; // 元音出现在次数 int numConsonant = lengthName / 2; // 辅音出现在次数 string vovel = ""; for (int i=0; i<numVovel; i++) { vovel += VOVEL[i/V_TIME]; } string constant = ""; for (int i=0; i<numConsonant; i++) { constant += CONSONANT[i/C_TIME]; } sort(vovel.begin(), vovel.end()); sort(constant.begin(), constant.end()); // 元音也辅音交错输出 for (int i=0; i<constant.size(); i++) { cout << vovel[i] << constant[i]; } // 元音有可能多一个 if (vovel.size() > constant.size()) cout << vovel[numVovel-1]; cout << endl; } return 0; }
环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE
参考: 以下两处的解法也很不错, 值的借鉴.
http://www.cppblog.com/rakerichard/archive/2011/04/09/143799.html
http://blog.csdn.net/ra_winding/article/details/8218022