总而言之,是在luogu题解的帮助下,千辛万苦,,,终于A了
我们需要将 A 串 与 B 串 匹配
会想到 dp[ i ][ j ] ->A串中的 i 位置 正在与 B串中的 j 位置的字母匹配 的总方案数
注意:我们是 被动 移动 j 指针 , 主动 移动 i 指针
但是还有一个 K 的限制,怎么办呢? Ans : 加一维 K
dp[ i ] [ j ] [ k ] 表示 A串中的 前 i 位置 与 B串中的 前 j 位置的字母匹配(当前在 A [ i ] ,B [ j ] )已经划分了 k 份 时的 总方案数
我只想到了这里,然后 GG 了、
题解告诉我 :: 再加一维 表示当前字母 选 or 不选
这个选不选 是有限制条件的
未加 滚动数组 的 代码 : ( 也未取模 )
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define inf 0x7f7f7f7f
#define LL long long
using namespace std;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0'; c=getchar ();}
return wans*=flag;
}
int N,M,K;
char A[1004],B[205];
int dp[1004][205][205][2];
int main (){
N=wread(),M=wread(),K=wread();
scanf ("%s%s",A+1,B+1);
dp[0][0][0][0]=1;
for (int i(1);i<=N;++i){
dp[i][0][0][0]=1;
for (int j(1);j<=M;++j){
for (int k(1);k<=K;++k){
if (A[i]==B[j]){
dp[i][j][k][0] = dp[i-1][j][k][1] + dp[i-1][j][k][0] ;
dp[i][j][k][1] = dp[i-1][j-1][k-1][0] + dp[i-1][j-1][k-1][1] + dp[i-1][j-1][k][1];
}
else {
dp[i][j][k][0] = dp[i-1][j][k][1] + dp[i-1][j][k][0] ;
dp[i][j][k][1] = 0;//不选
}
// printf("%d %d\n", dp[i][j][k][0], dp[i][j][k][1]);
// system ("pause");
}
}
}
printf("%d\n",dp[ N ][ M ][ K ][0] + dp[ N ][ M ][ K ][1]);
return 0;
}
考虑到 : i 每次 只跟 i-1 有关::滚动数组来啦 而且 就滚动这一位 便够了
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define inf 0x7f7f7f7f
#define LL long long
using namespace std;
const int mod = 1000000007;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0'; c=getchar ();}
return wans*=flag;
}
int N,M,K;
char A[1004],B[205];
int dp[2][205][205][2];
int main (){
N=wread(),M=wread(),K=wread();
scanf ("%s%s",A+1,B+1);
dp[0][0][0][0]=dp[1][0][0][0]=1;
int top(0);
for (int i(1);;i^=1){
top++;
for (int j(1);j<=M;++j){
for (int k(1);k<=K;++k){
if (A[top]==B[j]){
dp[i][j][k][0] = ( dp[i^1][j][k][1] % mod + dp[i^1][j][k][0] % mod ) % mod;
dp[i][j][k][1] =( ( dp[i^1][j-1][k-1][0] % mod + dp[i^1][j-1][k-1][1] % mod ) % mod+ dp[i^1][j-1][k][1] % mod ) % mod;
}
else {
dp[i][j][k][0] = ( dp[i^1][j][k][1] % mod + dp[i^1][j][k][0] % mod ) % mod ;
dp[i][j][k][1] = 0;//不选
}
}
}
if (top==N) break;
}
printf("%d\n",(dp[ N&1 ][ M ][ K ][0] % mod + dp[ N&1 ][ M ][ K ][1] % mod ) % mod );
return 0;
}
总结:还要多刷题啊!!
这种 DP 模型 挺常见的,却弄不起,有点难受了