您的位置:首页 > 其它

ZOJ_Crossed Matchings DP

2011-10-01 13:04 260 查看
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
[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: