CSU 1690 期望DP + 数据结构

/*
首先题目你要理解清楚
对于每个一行的文本串,最后一个字符串是前面的问句的答案
每次可以在一个句子的一半打断他进行抢答
问最有得分的期望值

建一个字典树,字典树上的点存储的是字符串
但是本题奇特的方式在在于字典树上存储了两个值
    一个是正常的文本串顺序,用于遍历和存储文本串
    一个是对于每个句子的答案,有多少个句子可以在这个点回答此答案

最后按照期望DP的方式求解
标程写成递归就直接照搬了,实际上可以写成循环结构

*/

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000 + 5;
struct Node
{
    map<string,int> next;
    map<string,int> answer;
    double pro;
    int tot;
    void clear() {next.clear(); tot = 0; answer.clear();}
}node[MAXN];
char str[MAXN];
double solve(int i, vector<double>::iterator it, int left)
{
// printf("i = %d\n", i);
    if(left == 0) return 0;
    double ans1 = node[i].pro + *it;
    double ans2 = 0;
    for(auto v : node[i].next) {
        ans2 += solve(v.second, it + 1, left - 1) * node[v.second].tot;
    }
    return max(ans1, ans2 / node[i].tot);
}
int main()
{
    int t, n;
    while(scanf("%d%d", &t, &n) != EOF) {
        cin.getline(str, MAXN);
        int cnt = 0;
        node[cnt].clear();
        for(int j = 0 ; j < n ; j++){
            cin.getline(str, MAXN);
            string temp = "";
            int index = 0;
            string aanswer = "";
            for(int i = strlen(str) - 1 ; i >= 0 ; i--) {
                if(str[i] == ' ') break;
                else aanswer += str[i];
            }
// cout << " aanswer = " << aanswer << endl;
            node[0].answer[aanswer]++;
            for(int i = 0 ; str[i] != '\0' ; i++){
                if(str[i] != ' ') temp += str[i];
                else{
                    if(node[index].next.count(temp) == 0){
                        node[index].next[temp] = ++cnt;
                        node[cnt].clear();
                    }
                    node[index].tot++;
                    index = node[index].next[temp];
                    node[index].answer[aanswer]++;
                    temp = "";
                }
            }
            node[index].tot++;
// temp += str[i];
// if(node[index].next.count(temp) == 0){
// node[index].next[temp] = ++cnt;
// node[cnt].clear();
// }
// node[index].tot++;
// index = node[index].next[temp];
// node[index].tot++;
        }
        for(int i = 0 ; i <= cnt ; i++){
                int mmax = 0;
                int sum = 0;
                for(auto v : node[i].answer) mmax = max(mmax, v.second), sum += v.second;
                node[i].tot = sum;
                node[i].pro = 1.0 * mmax / node[i].tot;
        }
// for(int i = 0 ; i <= cnt ; i++)
// printf("i = %d, pro = %f, tot = %d\n", i, node[i].pro, node[i].tot);
        vector <double> best(t + 1);
        for(int i = t - 1 ; i >= 0 ; i--)
            best[i] = solve(0, best.begin() + i + 1, t - i);
        printf("%.10f\n", best[0]);
    }
    return 0;
}

你可能感兴趣的:(CSU 1690 期望DP + 数据结构)