哇哇哇哇。。又A了一道。。
刚写出来的,感觉好激动。。
下午的时候看了下题目,题目大意为两行数字,上下相同的数字连线算一次匹配,求可能的最大匹配,规则是:I 连线必须且只能被另一条直线穿过。且这两条直线代表的数字不能相同。II 一个数字只能有一条连线。
刚开始没什么想法,也有想到dp,不过没想到具体怎么实现。。
晚上又仔细看了下,感觉dp应该可以做出来,用了好多for循环,不过如果按我的思路来理解会很简单的。。
dp[i][j]表示第一行数字从第i个到n,第二行数字从第j个到m,这么些数字有多少个匹配。
对于dp[i][j-1],只需要讨论b[j-1]与第一行的a[i]...a[n]的匹配情况。。
看代码:
# include<stdio.h> # include<string.h> int a[105],b[105],n,m,dp[105][105]; int main() { int i,j,t,k,h,s,flag,max; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(j=1;j<=m;j++) scanf("%d",&b[j]); for(j=1;j<=m;j++) { dp[n][j]=0; dp[n+1][j]=0; } for(i=1;i<=n;i++) { dp[i][m]=0; dp[i][m+1]=0; } dp[n+1][m+1]=0;/*特别注意,刚开始就是少加了这句话而wa了好几次*/ for(i=n-1;i>=1;i--) for(j=m-1;j>=1;j--) { max=dp[i][j+1];/*初始化为没有与b[j]匹配的情况*/ for(k=i+1;k<=n;k++) { if(b[j]==a[k]) { flag=0; for(h=j+1;h<=m;h++) { if(b[h]==b[j]) continue;/*两个连线 的数字不能相等*/ for(s=i;s<k;s++) { if(b[h]==a[s]) {flag=1;break;} } if(flag==1) break; } if(flag==1) { if(max<dp[k+1][h+1]+2) max=dp[k+1][h+1]+2;/*如果找到一组匹配*/ } } } dp[i][j]=max; } printf("%d\n",dp[1][1]); } return 0; }