题意:给出两个01字符串s1,s2.每次改变s1上m个位置的字符。问k步之后使得s1变为s2的方法有多少种。
解法:DP,关键是状态的设计。考虑还是唯一性和可传递性。dp[i][j]表示第i步后有j个不同到目标的走法数。记忆化搜索dp[0][dif](dif表示初始时不同字符的个数)。转移时候枚举选择情况即可。
代码:
/****************************************************** * author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> //freopen ("in.txt" , "r" , stdin); using namespace std; #define eps 1e-8 const double pi=acos(-1.0); typedef long long LL; const int Max=110; const int INF=1000000009; int n,k,m; string s1,s2; LL C[Max][Max]; int init() { for(int i=0; i<Max; i++) for(int j=0; j<=i; j++) C[i][j]=j?(C[i-1][j-1]+C[i-1][j])%INF:1; } LL dp[Max][Max]; int dif; LL dfs(int step,int num) { if(dp[step][num]!=-1) return dp[step][num]; LL ans=0; for(int i=0; i<=num; i++) { if(i+n-num<m) continue; if(i>m) break; ans=(ans+(C[num][i]*C[n-num][m-i])%INF*dfs(step+1,num-i+m-i))%INF; } return dp[step][num]=ans; } int main() { init(); while(scanf("%d%d%d",&n,&k,&m)==3) { dif=0; memset(dp,-1,sizeof dp); cin>>s1>>s2; for(int i=0; i<n; i++) if(s1[i]!=s2[i]) dif++; dp[k][0]=1; for(int i=1;i<=n;i++) dp[k][i]=0; cout<<dfs(0,dif)<<'\n'; } return 0; }
zoj3791(An Easy Game) DP
时间: 2024-10-06 16:16:36