[DP] poj1080

O(n^2)

/*poj1080
Sample
 	AGTGATG 
 	-GTTA-G 
 	score : (-3)+5+5+(-2)+5+(-1) +5=14.
  	每次读入2个字符串只有A,T,C,G
  	可以做3个操作:
  	1.删除目标串一个字符 2.删除原串一个字符,代价是a[?]['-']见表格
	3.改变一个字符代价是a[x][y]
	求代价最小的使2个字串相同的方法。
	dp[i][j]是原串第i个对应目标串第j个的最小代价
	dp[i][j]=max(dp[i-1][j]+Del[i]-Del[i-1],dp[i-1][k]+Del1[j-1]-Del1[k]+a[s2[i-1]][s1[j-1]])
 */
import java.util.*;
public class Main 
{
	static int min(int a,int b){return (a<b)? a:b;}
	static int max(int a,int b){return (a>b)? a:b;}
	public static void main(String[] args) 
	{
		Scanner cin=new Scanner(System.in);
		int n,dp[][]=new int [370][390],a[][]=new int [370][390];
		a['A']['A']=5; a['A']['C']=-1;a['A']['G']=-2;a['A']['T']=-1;a['A']['-']=-3;
		a['C']['A']=-1;a['C']['C']=5; a['C']['G']=-3;a['C']['T']=-2;a['C']['-']=-4;
		a['G']['A']=-2;a['G']['C']=-3;a['G']['G']=5; a['G']['T']=-2;a['G']['-']=-2;
		a['T']['A']=-1;a['T']['C']=-2;a['T']['G']=-2;a['T']['T']=5; a['T']['-']=-1;
		a['-']['A']=-3;a['-']['C']=-4;a['-']['G']=-2;a['-']['T']=-1;a['-']['-']=0;
		n=cin.nextInt();
		while(n-->0)
		{
			int l1,l2;
			String st1,st2;
			char s1[]=new char [120],s2[]=new char [130];
			l1=cin.nextInt();
			st1=cin.next();
			s1=st1.toCharArray();
			l2=cin.nextInt();
			st2=cin.next();
			s2=st2.toCharArray();
			int Del1[]=new int [120],Del2[]=new int[120];
			Del1[0]=Del2[0]=0;
			for(int i=1;i<=l1;i++)
				Del1[i]=Del1[i-1]+a[s1[i-1]]['-'];
			for(int i=1;i<=l2;i++)
				Del2[i]=Del2[i-1]+a[s2[i-1]]['-'];
			for(int j=0;j<=l1;j++)
				dp[0][j]=Del1[j];
			for(int i=1;i<=l2;i++)
			{
				dp[i][0]=Del2[i];
				for(int j=1;j<=l1;j++)
				{
					dp[i][j]=dp[i-1][j]+Del2[i]-Del2[i-1];
					for(int k=0;k<j;k++)
						dp[i][j]=max(dp[i][j], dp[i-1][k]+Del1[j-1]-Del1[k]+a[s2[i-1]][s1[j-1]]);
				}
			}
			int Ans=Del2[l2]+Del1[l1];
			for(int i=1;i<=l2;i++)
				Ans=max(Ans, dp[i][l1]+Del2[l2]-Del2[i]);
			System.out.println(Ans);
		}
		return ;    
	}
}

O(n^2) 只需要从{ ( i-1 , j ) , ( i , j-1 ) , ( i-1 , j-1 ) } 3个点转移 

import java.util.*;
public class Main 
{
	static int min(int a,int b){return (a<b)? a:b;}
	static int max(int a,int b){return (a>b)? a:b;}
	public static void main(String[] args) 
	{
		Scanner cin=new Scanner(System.in);
		int n,dp[][]=new int [370][390],a[][]=new int [370][390];
		a['A']['A']=5; a['A']['C']=-1;a['A']['G']=-2;a['A']['T']=-1;a['A']['-']=-3;
		a['C']['A']=-1;a['C']['C']=5; a['C']['G']=-3;a['C']['T']=-2;a['C']['-']=-4;
		a['G']['A']=-2;a['G']['C']=-3;a['G']['G']=5; a['G']['T']=-2;a['G']['-']=-2;
		a['T']['A']=-1;a['T']['C']=-2;a['T']['G']=-2;a['T']['T']=5; a['T']['-']=-1;
		a['-']['A']=-3;a['-']['C']=-4;a['-']['G']=-2;a['-']['T']=-1;a['-']['-']=0;
		n=cin.nextInt();
		while(n-->0)
		{
			int l1,l2;
			String st1,st2;
			char s1[]=new char [120],s2[]=new char [130];
			l1=cin.nextInt();
			st1=cin.next();
			s1=st1.toCharArray();
			l2=cin.nextInt();
			st2=cin.next();
			s2=st2.toCharArray();
			int Del1[]=new int [120],Del2[]=new int[120];
			Del1[0]=Del2[0]=0;
			for(int i=1;i<=l1;i++)
				Del1[i]=Del1[i-1]+a[s1[i-1]]['-'];
			for(int i=1;i<=l2;i++)
				Del2[i]=Del2[i-1]+a[s2[i-1]]['-'];
			for(int j=0;j<=l1;j++)
				dp[0][j]=Del1[j];
			for(int i=1;i<=l2;i++)
			{
				dp[i][0]=Del2[i];
				for(int j=1;j<=l1;j++)
				{
					dp[i][j]=dp[i-1][j]+Del2[i]-Del2[i-1];
					dp[i][j]=max(dp[i][j],dp[i][j-1]+Del1[j]-Del1[j-1]);
					dp[i][j]=max(dp[i][j], dp[i-1][j-1]+a[s2[i-1]][s1[j-1]]);
				}
			}
			System.out.println(dp[l2][l1]);
		}
		return ;    
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值