poj1692(区间记忆化dp)

来源:互联网 发布:linux snmpwalk 下载 编辑:程序博客网 时间:2024/06/14 15:56

题意:上下两行数相连,相等的才可以相连,并且每条线必须且只能与其他一条线相交(要同时满足相交的两条线的数不相等)。问给的两行数最多可以连几条线。

解法: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-8typedef 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;}

0 0