题意:上下两行数相连,相等的才可以相连,并且每条线必须且只能与其他一条线相交(要同时满足相交的两条线的数不相等)。问给的两行数最多可以连几条线。
解法:ans[i][j]记录着上面i,和下面j下标之后的数中最多可以连多少条,记忆化搜索dfs(0,0)就可以了。搜索时候,如果用到了i,则贪心在下面选相等的。用到j同理。
代码:
/**************************************************** * author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> using namespace std; #define eps 1e-8 typedef long long LL; int ans[1100][1100]; int num1[1100]; int num2[1100]; int n,m; bool OK(int *p,int left,int right,int t) { for(int i=left; i<=right; i++) { if(p[i]==t) return true; } return false; } int dfs(int i,int j) { if(i>n-2||j>m-2) return 0; if(ans[i][j]!=-1) return ans[i][j]; int res=max(dfs(i+1,j),dfs(i,j+1)); int k=0; for(k=i+1; k<n; k++) { if(num1[k]==num2[j]) break; } if(k!=n) { for(int h=j+1; h<m; h++) { if(num2[h]==num2[j])continue; if(OK(num1,i,k-1,num2[h])) { res=max(res,dfs(k+1,h+1)+2); break; } } } for(k=j+1; k<m; k++) { if(num2[k]==num1[i]) break; } if(k!=m) { for(int h=i+1; h<n; h++) { if(num1[h]==num1[i])continue; if(OK(num2,j,k-1,num1[h])) { res=max(res,dfs(h+1,k+1)+2); break; } } } return ans[i][j]=res; } int main() { int t; cin>>t; while(t--) { memset(ans,-1,sizeof ans); scanf("%d%d",&n,&m); for(int i=0; i<n; i++) scanf("%d",num1+i); for(int i=0; i<m; i++) scanf("%d",num2+i); cout<<dfs(0,0)<<‘\n‘; } return 0; }
poj1692(区间记忆化dp),码迷,mamicode.com
原文地址:http://blog.csdn.net/xiefubao/article/details/24841059