【基础完全搜索】USACO Bronze 2019 January - 猜动物Guess the Animal
题目描述
当奶牛贝茜和她的朋友艾尔西玩腻了常见的贝壳游戏后,她们喜欢玩另一个经典游戏"猜动物"。
游戏开始时,贝茜会在心中选定一种动物(大多数时候她都会选奶牛,这让游戏变得相当无聊,不过偶尔贝茜也会发挥创意选择其他动物)。接着艾尔西通过提出一系列问题来推断贝茜选择的动物。每个问题都会询问该动物是否具有某种特定特征,贝茜则用"是"或"否"来回答。例如:
艾尔西:“这种动物会飞吗?”
贝茜:“不会”
艾尔西:“这种动物吃草吗?”
贝茜:“吃”
艾尔西:“这种动物产奶吗?”
贝茜:“产”
艾尔西:“这种动物会哞哞叫吗?”
贝茜:“会”
艾尔西:“那我猜这是头奶牛。”
贝茜:“答对了!”
如果我们把"候选集合"定义为当前所有符合艾尔西已提问特征的动物集合,那么艾尔西会持续提问,直到候选集合只剩一种动物,这时她就会宣布答案。每个问题中,艾尔西会从候选集合中某个动物的特征里选取提问(即使这个特征可能无法进一步缩小候选范围)。她绝不会重复询问同一个特征。
已知贝茜和艾尔西了解的所有动物及其特征,请计算在确定正确答案前,艾尔西可能获得的最大"是"回答次数。
输入格式
第一行输入动物数量 (2≤N≤1002≤N≤1002≤N≤100)。
接下来 NNN 行,每行描述一个动物,格式为:动物名称开头,接着一个整数 (1≤K≤1001≤K≤1001≤K≤100),然后是 KKK 个该动物的特征。
动物名称和特征都是由不超过 202020 个小写字母 (a..z
) 组成的字符串。任意两个动物的特征组合都不会完全相同。
输出格式
输出一个整数,表示游戏结束前艾尔西可能获得的最大"是"回答次数。
输入输出样例
输入 #1
4
bird 2 flies eatsworms
cow 4 eatsgrass isawesome makesmilk goesmoo
sheep 1 eatsgrass
goat 2 makesmilk eatsgrass
输出 #1
3
样例说明
在这个样例中,艾尔西最多能获得 333 次"是"的回答(如上文对话所示),无法获得超过 333 次的"是"回答。
提交链接
Guess the Animal
思路分析
关键观察:最多“是”回答的情况是:她先问某一对动物共有的所有特征(每个都答“是”,但这两个动物仍都在候选集合里),然后再问一个只属于其中一个的额外特征得到最后一个“是”使候选集合缩到唯一。
因此:答案 = 任意一对动物之间共有特征数的最大值 + 1。
-
枚举所有动物对
对于所有 i<ji<ji<j 的动物对(即每一对不同动物),计算它们之间的共有特征数。
具体做法是:对第 iii 只动物的每个特征 ititit,再和第 jjj 只动物的每个特征 isisis 逐一比较,相等时计数 same++same++same++。
-
维护最大共有特征
每对算出的共有特征数 samesamesame 和当前记录的最大 MxMxMx 比较,取较大者。
循环结束后,MxMxMx 就是任意一对动物之间共有特征数的最大值。
-
输出最终答案
输出 Mx+1Mx + 1Mx+1,即在最糟情况下能得到的最多“是”回答次数。
时间复杂度:O(n2⋅K2)O(n^2 \cdot K^2)O(n2⋅K2)
参考代码:
#include <bits/stdc++.h>
using namespace std;int main()
{// freopen("guess.in", "r", stdin);// freopen("guess.out", "w", stdout);int n, mx = 0, id;cin >> n;vector<int> k(n + 1);vector<string> animal(n + 1);vector<vector<string>> Te(n + 1);map<string, int> mp;for (int i = 1; i <= n; i++){cin >> animal[i]; // 动物的名字cin >> k[i]; // k个特征for (int j = 0; j < k[i]; j++){string s;cin >> s; // 每一个特征Te[i].push_back(s); // 第i个动物的每一个特征}}int Mx = 0;//求任意两个动物之间的共同特征for(int i = 1; i <= n; i++){for(int j = i + 1; j <= n; j++){int same = 0;for(auto it : Te[i])for(auto is : Te[j])if(it == is)same++;Mx = max(Mx , same);}}cout << Mx + 1;return 0;
}