Letter by Letter 字典树+dp

来源:互联网 发布:淘宝网男士短袖 编辑:程序博客网 时间:2024/06/06 20:14

题目链接:

Letter by Letter

题目大意:

给你n个单词, 每个单词的长度都是k, 这个题目是交互式的, 你每次猜出n个单词里面的一个, 每次猜一个字母, 交互程序会给出0(错误), 1(正确)两个回复, 从第一个字母开始猜, 每猜对一个就接着猜下一个单词, 直到程序给出k个1(全部猜出来了)
但是这个交互器会尽可能让你多猜, 也就是说, 它会一直给出0, 直到不能在给0 (例如说共有两个单词abcd, bcad, 你第一次猜a, 它会给出0, 然后你只能再猜b, 它不能再给出0, 因为再给出0就没办法继续下去了; 但如果你第一次猜b, 它还是会给出0, 然后你只能再猜a, 它不得不给出1)
题目要求你猜测最小次数猜出这个单词

解题思路

很容易想到用字典树把所有单词存下来, 然后沿着树往下猜
因为无论你猜什么, 交互器都会给出0, 直到只剩下最后一个选项可以猜, 所以我们要把最坏的选项最先猜(交互器会否定这个答案), 最好的选项最后一个猜(交互器会给出1)
dp[i] := 以节点i为根节点, 猜到结束所需要猜测的的次数(最坏情况)
很明显, 在叶子处, dp = 0;
对于其他节点, 子节点树为n, dp[i] = max{node[i]->son[j]->dp + i}, 1<=j<=k
要使dp[i]最小, 我们应该让子节点以其dp值从小到大排序, 这样得出的dp[i]最小
然后每次按子节点的dp值, 从大到小猜

代码

#include <iostream>#include <algorithm>#include <vector>#include <cstdio>using namespace std;const int MAXN = 1E5 + 100;struct node{    bool flag;    int dp;    node * nxt[26];    node()    {        dp = 0;        flag = 0;        fill(nxt, nxt+26, nullptr);    }};node * root;void insert(const char * s){    node * p = root;    for(int i=0; s[i]!='\0'; ++i)    {        if(p->nxt[s[i]-'a'] == nullptr) p->nxt[s[i]-'a'] = new node;        p = p->nxt[s[i]-'a'];    }    p->flag = 1;}int n, k;char s[MAXN];void dfs(node * root){    vector<int> dps;    for(int i=0; i<26; ++i)    {        if(root->nxt[i] != nullptr)         {            dfs(root->nxt[i]);            dps.push_back(root->nxt[i]->dp);        }    }    sort(dps.begin(), dps.end(), greater<int>());    for(int i=0; i<(int)dps.size(); ++i)    {        if(dps[i]+i+1 > root->dp) root->dp = dps[i]+i+1;    }}void solve(node * root){    vector<pair<int, int>> dps;    for(int i=0; i<26; ++i)        if(root->nxt[i] != nullptr) dps.push_back({root->nxt[i]->dp, i});    sort(dps.begin(), dps.end(), greater<pair<int, int>>());    for(int i=0; i<(int)dps.size(); ++i)    {        cout << char(dps[i].second+'a') <<endl;        int ans;        cin >> ans;        if(ans)        {            solve(root->nxt[dps[i].second]);            break;        }    }}int main(){    root = new node;    cin >> n >> k;    for(int i=0; i<n; ++i)    {        cin >> s;        insert(s);    }    dfs(root);    solve(root);    return 0;}