Luogu 2679(dp)(NOIP 2015)

来源:互联网 发布:淘宝订单编号生成规则 编辑:程序博客网 时间:2024/06/07 19:51

传送门

NOIP 2015 D2T2

题解:

定义dp[i][j][k]为a串前i个字符,b串前j个字符,分成k段的方案数(a[i]必须选)。

定义sum[i][j][k]为a串前i个字符,b串前j个字符,分成k段的方案数(a[i]可选可不选)。

直接来要爆空间,所以第一维采用滚动数组优化。

那么两个数组互相转移

dp[cur][j][k]=sum[cur^1][j-1][k-1]+dp[cur^1][j-1][k](重新作为一段/和之前的一起凑成现有的一段),条件:a[i]==b[j]

sum[cur][j][k]=sum[cur^1][j][k]+dp[cur][j][k](所有之前的方案/当前选第i位的方案)

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int MAXN=1004,MAXM=204,MOD=1e9+7;int n,m,K;char a[MAXN],b[MAXM];int dp[2][MAXM][MAXM],sum[2][MAXM][MAXM];//a串前i个k段组成b串前j个(i必须选),a串前i个k段组成b串前j个(所有情况)int main() {//freopen("P2679.in","r",stdin);while (~scanf("%d%d%d",&n,&m,&K)) {scanf("%s%s",a+1,b+1);memset(dp,0,sizeof(dp));memset(sum,0,sizeof(sum));int cur=1;sum[cur^1][0][0]=1;for (int i=1;i<=n;++i) {sum[cur][0][0]=1;for (int j=1;j<=m;++j)for (int k=1;k<=K;++k) {dp[cur][j][k]=(a[i]==b[j])?(sum[cur^1][j-1][k-1]+dp[cur^1][j-1][k])%MOD:0;sum[cur][j][k]=(sum[cur^1][j][k]+dp[cur][j][k])%MOD;}cur^=1;}printf("%d\n",sum[cur^1][m][K]);}return 0;}


原创粉丝点击