UVa10723 - Cyborg Genes
这题我能想到的解决方法是:
最优解的长度好找,两串的长度和-LCS;
根据anslen,枚举出解的数目。。。但想不出简单有效的枚举方法,这种做法可能超时
网上看大神的博客后,发现大家都用的此方法:
最长目标串的长度为两串和减去最大公共子序列;
最长目标串的数量就是所有长度相同的情况的数量加和(路径的加和)(具体做法详见代码)
对于解的数量的求取我想了半天没有彻底的想明白,这也许说明我对LCS这方面的实现原理还是理解的不够透彻
需要注意的地方:1.有可能有空串
2.两串长度为30的串,最坏情况下合成的串有2^30次方
分析+学习:40分钟左右
coding+debug:15分钟左右
我还是蒟蒻..........能成长起来吗?
现在的我不敢说不行,也不得不说不行
寒假开学,中午到的校,在寝室坐不住,下午两天就跑机房来了,昨晚赶火车到现在一共睡了两个点不到= =。。一路上慌慌张张,生怕别人知道我是来干啥的。。。哎
怕的不是别人会崇拜,怕的是嘲笑
/* * Author: Bingo * Created Time: 2015/3/6 14:37:20 * File Name: uva 10723.cpp */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <stack> #include <queue> #include <set> #include <time.h> using namespace std; const int maxint = -1u>>1; unsigned int dp[40][40]; unsigned int f[40][40]; int T; string sa,sb; int main () { while (cin>>T){ int c=0; getchar(); while (T--){ c++; char s[50]; gets(s);sa=s;gets(s);sb=s; long long lena,lenb; lena=sa.size(); lenb=sb.size(); memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); for (int i=0;i<=lena;i++) f[i][0]=1; for (int i=0;i<=lenb;i++) f[0][i]=1; for (int i=1;i<=lena;i++) for (int j=1;j<=lenb;j++) { if (sa[i-1]==sb[j-1]){ dp[i][j]=dp[i-1][j-1]+1; f[i][j]=f[i-1][j-1]; }else { if (dp[i-1][j]>dp[i][j-1]){ dp[i][j]=dp[i-1][j]; f[i][j]=f[i-1][j]; } if (dp[i-1][j]<dp[i][j-1]){ dp[i][j]=dp[i][j-1]; f[i][j]=f[i][j-1]; } if (dp[i-1][j]==dp[i][j-1]){ dp[i][j]=dp[i-1][j]; f[i][j]=f[i-1][j]+f[i][j-1]; } } } cout << "Case #"<<c<<": "<<lena+lenb-dp[lena][lenb]<<" "<<f[lena][lenb]<<endl; } } }
附:
A后再去网上研究其他大神代码,找到一个利用递归,记忆化搜出所有解的数目的code
0.012s过的,速度很不错了
这不正是前几个题所体现的原理嘛?看样子我还是没想起来。
由此领悟到了一条道理:当想枚举所有情况搜时,可以用递归暴搜,然后加 记忆化 优化
转:http://blog.csdn.net/shiqi_614/article/details/7013708