CODEVS 1040统计单词个数

来源:互联网 发布:金融数据分析师待遇 编辑:程序博客网 时间:2024/06/13 18:26

对于这种序列型的动态规划,常用的处理方案是利用W[l][r]表示从l到r的序列所能得到的最大目标函数值。
由于本题还有一个划分次数的限制,因此,容易想到的是把常用方案改写成
W[l][r][limit]这种形式。
但是显然这种形式的维护效率很低。实际上,经过仔细思考,要计算出最后的答案W[0][end][limit],并不需要求出所有的W值,而只需要求出limit为0的时候的全部W[l][r]和l为0的时候的全部W[r][limit]即可。

/*1040 统计单词个数  2001年NOIP全国联赛提高组时间限制: 1 s空间限制: 128000 KB题目等级 : 黄金 Gold题解题目描述 Description给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)(管理员注:这里的不能再用指的是位置,不是字母本身。比如thisis可以算做包含2个is)。单词在给出的一个不超过6个单词的字典中。要求输出最大的个数。输入描述 Input Description第一行为一个正整数(0<n<=5)表示有n组测试数据每组的第一行有二个正整数(pk)p表示字串的行数;k表示分为k个部分。接下来的p行,每行均有20个字符。再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)接下来的s行,每行均有一个单词。输出描述 Output Description每行一个整数,分别对应每组测试数据的相应结果。样例输入 Sample Input11 3thisisabookyouareaoh4isaoksab12 3thisisabookyouareaohthisisabookyouareaoh4isaoksab样例输出 Sample Output7*/#include<iostream>#include<algorithm>#include<cstdio>#include<string>#include<cstring>#include<vector>using namespace std;/*通过DP获得以下两个数组两个数组(以下的r都视为超尾指针)1.W[l][r]       l到r这一段的最多能有多少个单词计算算法 :W[r][r] = 0;W[l - 1][r] = W[l][r] + 1(如果存在text[l]开头的当初的话)2.V[r][t]       从头部到r的这一段,经过t次划分,存在多少个单词计算算法:V[r][0] = W[0][r],V[0][t] = 0;V[r][t] = MAX(...V[m][t - 1] + W[m][r]...)(t <= m < r)*/int W[250][250];int V[250][50];string text,buf;vector<string>word;void input(string & text,int p){    //输入字符串 p行    text.clear();    word.clear();    for (int i = 0; i < p; i++){        cin >> buf;        text += buf;    }    int Num;    cin >> Num;    for (int i = 0; i < Num; i++){        cin >> buf;        word.push_back(buf);    }}bool check(int l,int r){    //检查是否存在字符串    int i,j;    buf.resize(r - l);    copy(text.begin() + l, text.begin() + r, buf.begin());    for (i = 0; i < word.size(); i++){        int len = word[i].size();        if (len > buf.size())continue;        for (j = 0; j < len; j++){            if (word[i][j] != buf[j])break;        }        if (j == len)return true;    }    return false;}void CalW(int len){    //计算W的值    int l,r;    for (r = len; r > 0; r--){        W[r][r] = 0;        for (l = r - 1; l >= 0; l--){            W[l][r] = W[l + 1][r];            if (check(l,r))W[l][r]++;        }    }}void CalV(int len,int Tmax){    int r, t, i;    memset(V, 0, sizeof(V));    for (r = 1; r <= len; r++)V[r][0] = W[0][r];    for (t = 1; t <= Tmax; t++){        for  (r = 1; r <= len; r++){            for (i = t; i < r; i++){                V[r][t] = max(V[r][t], V[i][t - 1] + W[i][r]);            }        }    }}int main(void){    int i, j, T;    cin >> T;    for (int TT = 0; TT < T; TT++){        cin >> i >> j;        input(text,i);        CalW(i * 20);        CalV(i * 20,j - 1);//分成j个部分,说明被分了j - 1次        cout << V[text.size()][j - 1] << endl;    }    return 0;}
0 0
原创粉丝点击