NOIP 2001统计单词个数 解题报告(记忆化搜索)

来源:互联网 发布:校招的数据分析岗多吗 编辑:程序博客网 时间:2024/04/29 12:53

在线评测:

http://codevs.cn/problem/1040/


整体思路:

,据说是一道化分型DP的题,,然而感觉我想出来的DP够炸时间炸死好几条命的了,,,于是感觉记忆化搜索可以大量减少没有用的dp。然后就记忆化了,,,不断地把一个区间分成两半,然后去搜,,每次枚举中间点和分成几个,搜下去就好了。。

失误之处:

1、开始我傻到把dfs(i,j,k)直接写成dp(i,j,k),,然后竟然神tmd过了60分,,,,,,我在想是出题人傻还是我更傻,,,

2、后来没想到 在枚举两边分配分成几个的时候需要考虑分配的分成几个需要 》= 这一块的元素总个数。。

3、这道题每次dfs的时候分配的分成几个无需减少1,,,,然而傻叉的我因为前几道题减少1而顺理成章的把这个也减少1了,,,竟然tmd过了80,,再次吐槽数据,,

体会心得:

仔细体会dfs的实际含义,改调用函数,还是直接访问自己想清楚,考虑好特殊情况~

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n,p,k,s,dp[210][210][50],lenn;
char tp[50],ch[300],zd[10][210];
int dfs(int x,int y,int k)
{
    int maxh = 0,maxk = 0;
    if (dp[x][y][k]) return dp[x][y][k];
    int maxn = 0;
    for (int  i = x;i <= y;i++)
    {
        for (int j = 1;j < k;j++)
        {
            if (j <= i - x + 1  && (k - j) <= (y - x  - (i - x )))
            {
             
            int tp = dfs(x,i,j) +dfs(i+1,y,k-j);
            if (tp > maxn) 
            {
                maxh = i;
                maxk = j;
                maxn = tp;
            }
        }
        }
    }
    dp[x][y][k] = maxn;
    return maxn;
}
int check(int x,int y)
{
    int tot = 0;
    for (int i = x;i <= y;i++)
    {
         
        for (int j = 1;j <= s;j++)
        {
            bool pd = true;
            int clen = strlen(zd[j]);
            for (int o = 0;o < clen;o++)
            {
                if (i + clen - 1 > y)
                {
                    pd = false;
                    break;
                }
                if (ch[i + o]!= zd[j][o])
                {
                    pd = false;
                    break;
                     
                }
            }
            if (pd) 
            {
                tot++;
                break;
            }
        }
    }
    return tot;
}
void init()
{
    for (int i = 0;i < lenn - 1;i++)
    {
        for (int j = i;j < lenn;j++)
        {
            dp[i][j][1] = check(i,j);
        }
    }
}
int main()
{
    scanf("%d",&n);
    for (int mi = 1;mi <= n;mi++)
    {
        scanf("%d%d",&p,&k);
        for (int i = 1;i <= p;i++)
        {
            scanf("%s",tp);
            for (int j = 0;j < 20;j++)
            {
                ch[(i - 1) * 20 + j] = tp[j];
            }
        }
        lenn = p * 20;
        scanf("%d",&s);
        for (int i = 1;i <= s;i++)
            scanf("%s",zd[i]); 
        memset(dp,0,sizeof(dp));
        init();
        int aans = dfs(0,lenn - 1,k);
        printf("%d\n",aans);
 
    }
    return 0;
}

0 0
原创粉丝点击