zoukankan      html  css  js  c++  java
  • 多校联合训练&hdu5791 Two

    hdu5791

    dp[i][j]表示的是序列A前i个数字和序列B前j个数字的公共子序列的总个数,那么的dp公式就可以这么表示

    理解一下此公式若最尾部的a[i]和b[j]相等的话,那么单独的a[i]和b[j]组成1个相同子序列。

    同时我们可以想一下之前的前i-1个子序列和前j-i个子序列再加上a[i]又能组成dp[i-1]个公共子序列。

    当然了,包含第i个数字的前i个序列a和前j-1个数字的序列b以及包含第j个数字的前j个序列b和前i-1个数字的序列a也要算上。

    所以把上面3种情况一合并就是前i-1个子序列a和前j个子序列b的公共子序列个数加上前i个子序列a和前j-1个子序列b的公共子序列个数再加1。

    这里包含了2倍的dp[i-1][j-1]个数。

    如果a[i]和b[j]不相等的话,减去一个dp[i-1][j-1]个数即可。

    本题中另一个注意点就是dp[i][j]可能为负,此时的处理方法是加上一个MOD

    代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #define MOD 1000000007
     5 #define LL long long
     6 using namespace std;
     7 LL dp[1005][1005];
     8 LL a[1005];
     9 LL b[1005];
    10 int main()
    11 {
    12     int n,m;
    13     while(~scanf("%d%d",&n,&m))
    14     {
    15         memset(dp,0,sizeof(dp));
    16         for(int i = 1;i<=n;i++)
    17             scanf("%d",&a[i]);
    18         for(int j = 1;j<=m;j++)
    19             scanf("%d",&b[j]);
    20         for(int i = 1;i<=n;i++)
    21         {
    22             for(int j = 1;j<=m;j++)
    23             {
    24                 if(a[i]==b[j])
    25                     dp[i][j]+=dp[i-1][j]+dp[i][j-1]+1;
    26                 else
    27                     dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];//极有可能出现负数
    28                 if(dp[i][j]<0)
    29                     dp[i][j]+=MOD;
    30                 dp[i][j]=dp[i][j]%MOD;
    31             }
    32         }
    33         printf("%I64d
    ",dp[n][m]);
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    vector在堆上还是在栈上(等待自己慢慢领悟吧)
    函数指针遇到typedef
    回调函数的代码示例
    _T和_L的区别
    MFC打开文件夹对话框
    C++中的抽象类和接口类
    UML图中继承和实现的区别
    扩展点(ExtensionPoint)
    组播(又称多播)是个好东西
    C++代码实现组播及归纳的流程图
  • 原文地址:https://www.cnblogs.com/fancy-itlife/p/5761043.html
Copyright © 2011-2022 走看看