poj 1080 一道经典的dp题
2012-07-13 10:49
267 查看
题目大意是:给定两组DNA序列,要你求出它们的最大相似度
每个字母与其他字母或自身和空格对应都有一个打分,求在这两个字符串中插入空格,让这两个字符串的匹配分数最大
解题思路,模仿动态规划里面经典的求最长公共子序列的方法
dp[i][j]表示字符串s1 1-i的和字符串序列s2 1-j的最长公共子序列的长度
当s1[i] == s2[j] 时dp[i][j] = dp[i-1][j-1] + 1
当s1[i] != s2[j]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
然后这个思想运用到这个题目中
dp[i][j]用来表示字符串s1 1-i的和字符串序列s2 1-j的最大相似度
value(s1[i], s2[j])表示字符s1[i]和s2[j]的匹配值
dp[i][j] 为 dp[i-1][j-1] + value(s1[i], s2[j]), dp[i-1][j] + value(s1[i], '-'), dp[i][j-1] + value('-', s2[j])中的最大值
这里要处理一下边界值
dp[0][0] = 0;
dp[0][j] = dp[0][j-1] + value('-', s2[j])
dp[i][0] = dp[i-1][0] + value(s1[i], '-');
dp[0][i]表示字符串s1前i个字符串和长度为i的空格串匹配的值
最后结果就为dp[len1][len2]。
代码:
#include
<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
char str1[120],str2[120];
int dp[120][120],t,len1,len2;
int matrix[5][5]={{5,-1,-2,-1,-3},
{-1,5,-3,-2,-4},
{-2,-3,5,-2,-2},
{-1,-2,-2,5,-1},
{-3,-4,-2,-1,0}};
map<char,int>mp;
void lcs()
{
int i,j;
dp[0][0]=0;
for(i=1;i<=len1;i++)
{
dp[i][0]=dp[i-1][0]+matrix[mp[str1[i]]][mp['-']];
}
for(i=1;i<=len2;i++)
{
dp[0][i]=dp[0][i-1]+matrix[mp['-']][mp[str2[i]]];
}
for(i=1;i<=len1;i++)
for(j=1;j<=len2;j++)
{
dp[i][j]=dp[i-1][j-1]+matrix[mp[str1[i]]][mp[str2[j]]]
;
dp[i][j]=max(dp[i][j],dp[i-1][j]+matrix[mp[str1[i]]][mp['-']]);
dp[i][j]=max(dp[i][j],dp[i][j-1]+matrix[mp['-']][mp[str2[j]]]);
}
}
int main()
{
mp['A']=0;mp['C']=1;mp['G']=2;mp['T']=3;mp['-']=4;
cin>>t;
while(t--)
{
scanf("%d %s",&len1,str1+1);
scanf("%d %s",&len2,str2+1);
lcs();
printf("%d\n",dp[len1][len2]);
}
return 0;
}
每个字母与其他字母或自身和空格对应都有一个打分,求在这两个字符串中插入空格,让这两个字符串的匹配分数最大
解题思路,模仿动态规划里面经典的求最长公共子序列的方法
dp[i][j]表示字符串s1 1-i的和字符串序列s2 1-j的最长公共子序列的长度
当s1[i] == s2[j] 时dp[i][j] = dp[i-1][j-1] + 1
当s1[i] != s2[j]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
然后这个思想运用到这个题目中
dp[i][j]用来表示字符串s1 1-i的和字符串序列s2 1-j的最大相似度
value(s1[i], s2[j])表示字符s1[i]和s2[j]的匹配值
dp[i][j] 为 dp[i-1][j-1] + value(s1[i], s2[j]), dp[i-1][j] + value(s1[i], '-'), dp[i][j-1] + value('-', s2[j])中的最大值
这里要处理一下边界值
dp[0][0] = 0;
dp[0][j] = dp[0][j-1] + value('-', s2[j])
dp[i][0] = dp[i-1][0] + value(s1[i], '-');
dp[0][i]表示字符串s1前i个字符串和长度为i的空格串匹配的值
最后结果就为dp[len1][len2]。
代码:
#include
<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
char str1[120],str2[120];
int dp[120][120],t,len1,len2;
int matrix[5][5]={{5,-1,-2,-1,-3},
{-1,5,-3,-2,-4},
{-2,-3,5,-2,-2},
{-1,-2,-2,5,-1},
{-3,-4,-2,-1,0}};
map<char,int>mp;
void lcs()
{
int i,j;
dp[0][0]=0;
for(i=1;i<=len1;i++)
{
dp[i][0]=dp[i-1][0]+matrix[mp[str1[i]]][mp['-']];
}
for(i=1;i<=len2;i++)
{
dp[0][i]=dp[0][i-1]+matrix[mp['-']][mp[str2[i]]];
}
for(i=1;i<=len1;i++)
for(j=1;j<=len2;j++)
{
dp[i][j]=dp[i-1][j-1]+matrix[mp[str1[i]]][mp[str2[j]]]
;
dp[i][j]=max(dp[i][j],dp[i-1][j]+matrix[mp[str1[i]]][mp['-']]);
dp[i][j]=max(dp[i][j],dp[i][j-1]+matrix[mp['-']][mp[str2[j]]]);
}
}
int main()
{
mp['A']=0;mp['C']=1;mp['G']=2;mp['T']=3;mp['-']=4;
cin>>t;
while(t--)
{
scanf("%d %s",&len1,str1+1);
scanf("%d %s",&len2,str2+1);
lcs();
printf("%d\n",dp[len1][len2]);
}
return 0;
}
相关文章推荐
- 半天痛苦换来的教训,做一道DP经典水题----最长公共子序列 POJ 2250
- poj 1080 Human Gene Functions(动态规划:经典DP)
- 0-1背包问题入门小结 动态规划(DP)经典题目 POJ324 POJ1276
- POJ 1185 炮兵阵地(经典状态压缩dp)
- POJ 1160:Post Office 邮局经典DP
- POJ 1080-Human Gene Functions(DP)
- 【经典dp】 poj 3671
- poj 1080 dp(sequence alignment)
- poj 2385 Apple Catching 经典dp
- POJ-1243 One Person (经典级dp)猜数字
- poj 1390 Blocks (经典区间dp 方块消除)
- poj 1080 DP
- POJ 1080 Human Gene Functions DP
- POJ 1655 - DP 树的重心,经典 #P
- POJ - 3280Cheapest Palindrome-经典区间DP
- poj 1080 Human Gene Functions(dp)
- poj 2096 Collecting Bugs 概率dp 入门经典 难度:1
- POJ 1185 经典dp
- POJ 2096 Collecting Bugs (概率DP经典入门题)
- 【poj 1080】Human Gene Functions DP(类最长公共子序列*)