zoukankan      html  css  js  c++  java
  • uoj#149

    dp

    没想出来 最先开始想 dp[i][j][k]表示s匹配到i,t匹配到j,当前分了k段的方案数

    s[i]==t[j] dp[i][j][k]+=dp[i-1][j-1][k-1] s[i]==t[j]&&s[i-1]==t[j-1] dp[i][j][k]+=dp[i-1][j-1][k] dp[i][j][k]+=dp[i-1][j][k]

    问题出在中间那个式子,但是我不知道怎么改,这样会多出来很多状态,比如说aabaab和aabk=1

    dp[5][2][1]=4 因为dp[5][2][1]+=dp[4][1][1] 但是这样会出现不连续的,第一个a和第5个a匹配了,因为上一个方案可能没选那位,但是我们当成可以接在上一个后面。

    那么我们再定义一个f[i][j][k]表示s匹配到i,t匹配到j,分成k段,i和j同时选的方案数。这样就解决了刚才的那个问题,dp[i][j][k]=dp[i-1][j][k]+f[i][j][k]

    s[i]==t[j] f[i][j][k]=f[i-1][j-1][k]+dp[i-1][j-1][k-1] 否则f[i][j][k]=0

    这样就可以转移了

    如果当前dp不满足一些转移的条件,我们可以创造一些条件,比如多设一个数组,在树形dp求直径也用到了这样的思路。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010, mod = 1000000007;
    int n, m, k, pre;
    int dp[2][N][N], f[2][N][N];
    char s[N], t[N];
    int main()
    {
        scanf("%d%d%d%s%s", &n, &m, &k, s + 1, t + 1);
        dp[0][0][0] = 1;
        for(int i = 1; i <= n; ++i)
        {
            pre ^= 1;
            dp[pre][0][0] = 1;
            for(int j = 1; j <= min(m, i); ++j)
                for(int x = 1; x <= min(j, k); ++x)
                {
                    dp[pre][j][x] = f[pre][j][x] = 0;
                    if(s[i] == t[j]) 
                        f[pre][j][x] = (f[pre ^ 1][j - 1][x] + dp[pre ^ 1][j - 1][x - 1]) % mod;
                    dp[pre][j][x] = (f[pre][j][x] + dp[pre ^ 1][j][x]) % mod;
                }
        }
        printf("%d
    ", dp[pre][m][k]);
        return 0;
    }
    View Code
  • 相关阅读:
    压缩命令
    常用命令7-帮助命令1
    常用命令6--文件搜索命令4-grep
    常用命令5--文件搜索命令3-find
    常用命令4-文件搜索命令 2- which
    【转】Castle开发系列文章
    【摘录】C#多线程编程
    优化一
    Value Shadowing(不明確的方式存取变量)
    portability flaw : file separator (可移植性缺陷:文件分隔符)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7185185.html
Copyright © 2011-2022 走看看