[ACM Day7]J.Just a Quiz

题目描述

给定两个正整数 t,N t , N 分别表示本次问答竞赛的时间和问题的数目,对于每个问题以一个问号作为结尾,后面是其的答案,问在给定的 t t 时间内最大期望能答对多少题?

数据范围

The first line contains two integers

(1<=t<=100,1<=N<=100000) ( 1 <= t <= 100 , 1 <= N <= 100000 )
the duration of the quiz and the number of questions. Each of the following N N lines contains a question, which is a space-separated list of words terminated by a question mark; and an answer, which is a single word.
Each word is a sequence of non-space ASCII printable characters, between the ASCII values of ‘!’ and ‘∼’. Only the last word of a question has a question mark (‘?’). You can assume that no question is a prefix of another and that punctuation marks are part of a word. Words spelled with different upper/lower case are assumed to be different.
It is guaranteed that the total number of word characters is at most 100000。

分析

看到单词的问题其实就应该直接想到字典树,不过这个是以一个单词作为一个节点来处理,对于每个单词维护两个map,一个记录其后继,一个记录当前这一位后继的个数,这样就可以dp来做啦。

#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
int _read(){
    char ch = getchar();
    int x = 0 , f = 1 ;
    while( !isdigit( ch ) )
           if( ch == '-' ) f = -1 , ch = getchar();
           else ch = getchar();
    while( isdigit( ch ) )
           x = (ch  - '0') + x * 10 , ch =  getchar();
    return x * f;
}
typedef long long ll;
const ll p1 = 197 , p2 = 179 , mod1 = 1e9 + 7 , mod2 = 1e9 + 9;
#define PII pair<ll,ll>
#define fr first
#define se second
string s;
PII gethash(){
    PII res( 0 , 0 );
    for( int i = 0 ; s[i] ; ++i ){
        ( res.fr = res.fr * p1 + s[i] ) %= mod1;
        ( res.se = res.se * p2 + s[i] ) %= mod2;
    }
    return res;
}
const int maxn = 100000 + 30;
struct Tire{
    map<PII , int> mp;
    map<PII , int> cnt;
    void cls(){
        mp.clear();
    }
} tree[maxn];
int cnt[maxn] , N , T , tot;
vector<int> g[maxn];
#define PB push_back
void build( int x ){
    int rt = 0 ; g[x].PB( rt ); cnt[rt]++;
    while( cin >> s ){
        PII t = gethash();
        if( tree[rt].mp.find( t ) == tree[rt].mp.end() ){
            tree[rt].mp[t] = ++tot;
            tree[tot].cls();
            rt = tot;
        }else rt = tree[rt].mp[t];
        g[x].PB( rt ); cnt[rt]++;
        if( s[s.length() - 1] == '?' ) break;
    }
    cin >> s;
    PII t = gethash();
    for( int i = 0 ; i < (int)g[x].size() ; ++i )
        tree[g[x][i]].cnt[t]++;
}
double f[111][maxn] , mx[maxn];
#define mapi map<PII,int>::iterator
inline void cmax( double &x , double y ){ x = (x > y ? x : y); }
inline double _max( double x , double y ){ return x > y ? x : y ; }
int main(){
    cin >> T >> N;
    tree[tot = 0].cls();
    rep( i , 1 , N ) build( i );
    rep( i , 0 , tot ){
        mx[i] = 0.0;
        for( mapi u = tree[i].cnt.begin() ; u != tree[i].cnt.end() ; ++u )
            cmax( mx[i] , ( 1.0 * (*u).se / cnt[i] ) );
    }
    rep( i , 1 , T ){
        per( j , tot , 0 ){
            double t = 0;
            for( mapi u = tree[j].mp.begin() ; u != tree[j].mp.end() ; ++u )
                t += f[i - 1][(*u).se] * cnt[(*u).se];  
            f[i][j] = _max( f[i - 1][0] + mx[j] , t / cnt[j] );
        }
    }
    printf("%.12lf\n" , (double)f[T][0]);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值