luogu【P2753】[USACO4.3]字母游戏Letter Game
这个题。。。一开始看了很久题目(并且问了机房几个大佬)才明白题意。。 (原题入口)
题意
大概是一开始给你一些字母出现的次数 你之后组成的单词(最多两个单词)每个字母出现次数 必须小于或等于标准(standard)的次数
其次是要满足你组成单词的 每个字符个数 * 该字符单个价值 最大。 如果有多解按字典序来。
自己的理解:
这个题目很良心 单词表可以去USACO官网上看。。都很短 而且给你的是按字典序来的 就不需要手动排序了
再其次楼下都讲了 很多单词存都不用存 一开始判断下就行了
对于这种东西 就应该用结构体存储 并且重载一些运算符 或者 成员函数 (因为很多操作是很重复的)
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cctype> 7 #include <iostream> 8 #define For(i, l, r) for(int i = (l); i <= (int)(r); ++i) 9 #define Fordown(i, r, l) for(int i = (r); i >= (int)(l); --i) 10 #define Set(a, v) memset(a, v, sizeof(a)) 11 using namespace std; 12 13 inline int read(){ 14 int x = 0, fh = 1; char ch; 15 for(; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1; 16 for(; isdigit(ch); ch = getchar()) x = (x<<1) + (x<<3) + (ch^'0'); 17 return x * fh; 18 } 19 20 const int N = 40010; 21 const int score[26]={2, 5, 4, 4, 1, 6, 5, 5, 1, 7, 6, 3, 5, 2, 3, 5, 7, 2, 1, 2, 4, 6, 6, 7, 5, 7}; 22 //当然要把这个表打出来了。。但我太懒了。。copy了一下redbag大神的。。 23 24 struct node { 25 char str[101]; 26 int dig[26]; //存储了每个单词出现的次数 27 28 void update () { 29 int n = strlen(str); 30 Set(dig, 0); 31 For (i, 0, n-1) 32 dig[str[i] - 'a'] ++; 33 } //更新每个字符出现的次数 34 35 int calc () { 36 int ans = 0; 37 For (i, 0, 25) 38 ans += dig[i] * score[i]; 39 return ans; 40 } //计算这个单词的得分 41 42 bool operator > (const node &rhs) const { 43 For (i, 0, 25) 44 if (dig[i] > rhs.dig[i]) return true; 45 return false; 46 } //比较单词每个字母出现次数多少 如果多的话 则不满足题目要求 47 48 node operator + (const node &rhs) const { 49 node ans; 50 Set(ans.dig, 0); 51 For (i, 0, 25) 52 ans.dig[i] = dig[i] + rhs.dig[i]; 53 return ans; 54 } //把两个单词出现次数加起来 55 }; 56 57 node standard, word[N]; 58 int cnt = 1; 59 struct ans_pair { 60 int word1, word2; //答案的词对 如果只有一个单词则第二个为0 这个存储的是单词的编号 61 }; 62 63 #include <vector> 64 vector <ans_pair> lt; //听说 不定长数组 和 答案序列 更配哦 (滑稽) 65 66 int ans_num = 0; 67 int main(){ 68 scanf ("%s", standard.str); 69 standard.update(); //把初始的标准更新 70 while (scanf ("%s", word[cnt].str) != EOF && word[cnt].str[0] != '.') { 71 word[cnt].update(); 72 if (word[cnt] > standard) continue; //如果不满足要求就不能存储 让下一个输入的覆盖掉 73 ++cnt; 74 } 75 --cnt; //去掉最后一个'.' 76 For (i, 1, cnt) { 77 int now_score = 0; //当前成绩 78 now_score = word[i].calc(); 79 if (now_score > ans_num) 80 {ans_num = now_score; lt.clear(); lt.push_back((ans_pair) {i, 0} );} //比原来答案大 就更新一下 81 else if (now_score == ans_num) lt.push_back((ans_pair) {i, 0} ); //相同就放入vector 82 83 For (j, i+1, cnt) { 84 node new_word = word[i] + word[j]; //计算合并后单词的dig 85 if (new_word > standard ) continue; //不满足要求就继续找 86 now_score = new_word.calc(); //计算成绩 87 if (now_score > ans_num) //同上 88 {ans_num = now_score; lt.clear(); lt.push_back((ans_pair) {i, j} );} 89 else if (now_score == ans_num) lt.push_back((ans_pair) {i, j} ); 90 } 91 } 92 93 printf ("%d\n", ans_num); 94 For (i, 0, lt.size()-1) { 95 int fir = lt[i].word1, sec = lt[i].word2; //first 第一个单词 second 第二个单词 96 if (sec) printf ("%s %s\n", word[fir].str, word[sec].str); 97 else printf ("%s\n", word[fir].str); //如果只有一个单词 输出第一个单词就好了 98 } 99 }