LightOJ 1013 - Love Calculator(DP)

来源:互联网 发布:node.js实战 电子书 编辑:程序博客网 时间:2024/04/29 08:56

题意:给你两个字符串str1,str2,要求求以这两个字符串为不下降子序列的字符串det最小长度,并且求出该字符串det的组合方式有多少种。

这个算是一道简单的DP题。第一个问题的关键是求两个字符串str1、str2的最长公共子序列。

第二个问题的关键:已知一个长度为n的字符串的组合方式为m1,长度为n+1的字符串组合方式为m2,则长度为n+1的字符串组合方式就是m2+=m*1;

 f[k+1][i+1][j]+=f[k][i][j];  //k为字符串det长度,i为字符串str1放置到det的长度,j为str2放置到det的长度。     

f[k+1][i][j+1]+=f[k][i][j];



//非递归版#include <cstdio>#include <cstring>typedef long long lld;int dp[50][50],ans,len1,len2;char str1[50],str2[50];lld f[100][50][50];int Dp(int n,int m){         //求最长公共子序列    int i,j;    for(i=0;i<n;i++) dp[i][0]=0;    for(j=0;j<m;j++) dp[0][i]=0;    for(i=1;i<=n;i++){        for(j=1;j<=m;j++){            if(str1[i-1]==str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;            else{                if(dp[i-1][j]>=dp[i][j-1])                         dp[i][j]=dp[i-1][j];                else dp[i][j]=dp[i][j-1];            }        }    }    return len1+len2-dp[n][m];}lld Dfs(){           //求组合方式    int i=0,j=0,k;    memset(f,0,sizeof(f));    f[0][0][0]=1;    for(k=0;k<ans;k++){      //k新字符串长度,i为str1长度,j为str2长度        for(i=0;i<=len1;i++){            for(j=0;j<=len2;j++){if(i==len1 && j!=len2)f[k+1][i][j+1]+=f[k][i][j];else if(i!=len1 && j==len2)f[k+1][i+1][j]+=f[k][i][j];else if(str1[i]==str2[j]) f[k+1][i+1][j+1]+=f[k][i][j];else{f[k+1][i+1][j]+=f[k][i][j];f[k+1][i][j+1]+=f[k][i][j];}}}    }    return f[ans][len1][len2];}int main() {    int t,cas;    scanf("%d",&t);    getchar();    for(cas=1;cas<=t;cas++){        gets(str1);        gets(str2);        len1=strlen(str1);len2=strlen(str2);        ans=Dp(len1,len2);        memset(f,-1,sizeof(f));        lld pos=Dfs();        printf("Case %d: %d %lld\n",cas,ans,pos);    }    return 0;}


//递归版#include <cstdio>#include <cstring>typedef long long lld;int dp[50][50],ans,len1,len2;char str1[50],str2[50];lld f[100][50][50];int Dp(int n,int m){    int i,j;    for(i=0;i<n;i++) dp[i][0]=0;    for(j=0;j<m;j++) dp[0][i]=0;    for(i=1;i<=n;i++){        for(j=1;j<=m;j++){            if(str1[i-1]==str2[j-1]) dp[i][j]=dp[i-1][j-1]+1;            else{                if(dp[i-1][j]>=dp[i][j-1])                    dp[i][j]=dp[i-1][j];                else dp[i][j]=dp[i][j-1];            }        }    }    return len1+len2-dp[n][m];}lld Dfs(int len,int n,int m){ if(f[len][n][m]!=-1)  return f[len][n][m];if(len==ans)  return n==len1&&m==len2;if(n==len1)  f[len][n][m]=Dfs(len+1,n,m+1);else if(m==len2)  f[len][n][m]=Dfs(len+1,n+1,m);else if(str1[n]==str2[m])  f[len][n][m]=Dfs(len+1,n+1,m+1);else f[len][n][m]=Dfs(len+1,n,m+1)+Dfs(len+1,n+1,m);return f[len][n][m];}int main() {    int t,cas;    scanf("%d",&t);    getchar();    for(cas=1;cas<=t;cas++){        gets(str1);gets(str2);        len1=strlen(str1);len2=strlen(str2);        ans=Dp(len1,len2); memset(f,-1,sizeof(f));        lld pos=Dfs(0,0,0);        printf("Case %d: %d %lld\n",cas,ans,pos);    }    return 0;}


原创粉丝点击