ZOJ_Crossed Matchings DP

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1425

DP,定义dp[i][j]为第一行中的前i个数和第二行中的前j个数,最多能构成多少对相交线段。因为题意中规定,任意一段合法的线段a有且只有一段线段b与之相交,且a!=b,由此可得:在这段线段之间将不会有其他新的线段了,因此可以定义转移方程为:

dp[i][j] = max{ dp[ii-1][jj-1] + 2 , dp[i-1][j] , dp[i][j-1] } ,其中a[ii] == b[j] && b[jj] == a[i] ,其中对于最后两个的解释是,a[i] 和 b[j] 都不参与构成相交线段。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define max(a,b) (a>b?a:b)

using namespace std;

int n,m;
int a[101],b[101] ;
int dp[101][101] ;

int DP()
{
	int ii,jj,i,j;
	memset(dp,0,sizeof(dp));
	
	for(i=2;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			if(j==1)
				continue ;	
			for(jj=j-1;jj>=1;jj--)				//寻找a[i] == b[jj]的点 
			{	
				if(a[i] == b[jj])	
					break ;	
			}	
			for(ii=i-1;ii>=1;ii--)				//寻找b[j] == a[ii]的点 
			{
				if(b[j] == a[ii])
					break ;	
			}
			if(jj==0 || ii==0)
			{
				dp[i][j] = max(dp[i-1][j] ,dp[i][j-1]) ;	
			}
			else{
				dp[i][j] = max(dp[i-1][j] ,dp[i][j-1]) ;
				if(a[i] != b[j])
					dp[i][j] = max(dp[i][j] ,dp[ii-1][jj-1]+2) ;
			}
		}	
	}	
	return dp[n][m] ;	
}

int main()
{
    //freopen("1in.txt","r",stdin);
    //freopen("1out.txt","w",stdout);
	int T;
	scanf("%d",&T) ;
	while(T--)
	{
		scanf("%d %d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=m;i++)
			scanf("%d",&b[i]);
		int ans = DP();	
		printf("%d\n",ans);	
	}
	 
    return 0;
}



你可能感兴趣的:(ZOJ_Crossed Matchings DP)