HDU 6078 Wavel Sequence

来源:互联网 发布:域名名词解释 编辑:程序博客网 时间:2024/06/07 12:12

我个人感觉这是一道递推题目。动态规划,好困!!!

怎么想递推公式呢。开始我是没有任何思路的,看了别人的题解,感觉确实和最长公共子序列很像

dp[i][j][0]代表以a[i]和b[j]结尾的波谷

dp[i][j][1]代表以a[i]和b[j]结尾的波峰

S[i][j][0]表示sum(dp[k][j][0] | 1<=k<=j-1)。 
S[i][j][1]则表示sum(dp[k][j][1] | 1<=k<=j-1)。 
那么对于每个a[i],只有存在j使得b[j]==a[i]时,dp[i][j][0]等于sum(S[i-1][k][1] | 1<=k<=j-1&&b[k]>a[i]),dp[i][j][1]等于sum(S[i-1][k][0] | 1<=k<=j-1&&b[k]<=a[i]-1). 

看这个配合着代码就很好理解这个递推的过程,sum【j】【0】就是在j这个位置,一共有多少种情况让B[j]做波谷.

看了题解算长了见识,不知道下次遇见能不能做

#include "cstdio"#include "iostream"#include "cstring"#include <algorithm>using namespace std;const int maxn= 2000+10;int a[maxn],b[maxn];long long dp[maxn][2],sum[maxn][2];const int mod=998244353;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)scanf("%d",&a[i]);        for(int i=1;i<=m;i++)scanf("%d",&b[i]);        long long ans=0;        memset(dp,0,sizeof(dp));        memset(sum,0,sizeof(sum));        for(int i=1;i<=n;i++)        {            long long cnt1=1,cnt0=0;            for(int j=1;j<=m;j++)            {               dp[j][0]=dp[j][1]=0;               if(a[i]==b[j]){                    dp[j][0]=cnt1,dp[j][1]=cnt0;               ans=(ans+cnt0+cnt1)%mod;               }               else if(a[i]>b[j])cnt0+=sum[j][0],cnt0%=mod;               else cnt1+=sum[j][1],cnt1%=mod;            }            for(int j=1;j<=m;j++)            {                sum[j][0]+=dp[j][0];                sum[j][1]+=dp[j][1];                sum[j][0]%=mod;                sum[j][1]%=mod;            }        }        printf("%lld\n",ans);    }    return 0;}