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 }

 

posted @ 2017-07-09 10:40  zjp_shadow  阅读(526)  评论(0编辑  收藏  举报