zoj3791(An Easy Game) DP

意甲冠军:给定两个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; }


版权声明:本文博主原创文章,博客,未经同意不得转载。

posted @ 2015-09-12 12:00  zfyouxi  阅读(152)  评论(0编辑  收藏  举报