每日一题(17): poj1080

1. 原来没有思路。因为LCS有点不熟。但是参考了网上的解法,有了思路,就自己写出来了。主要参考: 点击打开链接

2. 其实就是把之前的动态规划公式延伸了一维。因为之前虽然背包问题也可以是二维,但是毕竟可以化为一维。因为后一种状态只和其中一个index(j)有关。这也是可以化为一维的原因。但是此题不同,就是二维。当然,如果熟悉LCS,就可能会容易一点。公式:

dp[i][j] = max{dp[i-1][j-1]+value(a[i],b]j],dp[i][j-1]+value(-,b[j]), dp[i-1][j]+value(a[i],-)}

3. 注意边界。一边是0,就用‘-’,另一边字符串用字符。这应该可以理解的,也就是从实际上说的通的。00是0。

4. 为了保证有0边界,输入的时候需要对scanf里面的地址加1.这一点之前没有用过。

5. 因为在max里面的a写成b,导致出错。一定要小心。写程序的过程尤其慎重。因为debug的时候很困难。

下面是代码:

#include<iostream>
#include<stdio.h>
#include<string.h>

using namespace std;
//数据结构和变量
const int maxn = 110;
char a[maxn];
char b[maxn];
int dp[maxn][maxn];
int n1,n2;
int score[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}
};
//取两者之间的最大值
int big(int temp1,int temp2,int temp3)
{
int result = temp1;
if(result<temp2)
result=temp2;
if(result<temp3)
result = temp3;
return result;
}
//返回字母对应的下标。其实可以用hash的
int charIndex(char temp1)
{
int result;
switch(temp1)
{
case 'A': result = 0;break;
case 'C': result = 1;break;
case 'G': result = 2;break;
case 'T': result = 3;break;
case '-': result = 4;break;
}
return result;
}
//返回对比值
int value(char temp1, char temp2)
{
return score[charIndex(temp1)][charIndex(temp2)];
}
int main()
{
//freopen("input.txt","r",stdin);
int t;
cin >>t ;
int i,j;
while(t--)
{
//cin>>n1;
//输入数据
//此法甚妙
scanf("%d%s",&n1,a+1);
scanf("%d%s",&n2,b+1);
//初始化:边界
dp[0][0] = 0;
for(i = 1; i<=n1; i++)
{
dp[i][0] = value(a[i],'-')+dp[i-1][0];
}
for(j = 1; j<=n2; j++)
{
dp[0][j] = value(b[j],'-')+dp[0][j-1];
}
//开始动态规划:
//公式dp[i][j] = max{dp[i-1][j-1]+value(a[i],b]j],dp[i][j-1]+value(-,b[j]), dp[i-1][j]+value(b[i],-)}
for(i = 1; i<=n1; i++)
{
for(j = 1; j<=n2; j++)
{
dp[i][j] = big(dp[i-1][j-1]+value(a[i],b[j]),dp[i][j-1]+value('-',b[j]), dp[i-1][j]+value(a[i],'-'));
}
}
//输出结果
cout <<dp[n1][n2]<<endl;
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值