Ural(Timus) 1078. Segments

DP(DAG最长路)

题意:给出x轴上的线段的端点坐标,一个线段能覆盖另一个线段(端点不能相同),求出最多的线段覆盖并且从短到长给出路径。转化模型为DAG,求DAG上的最长路并且打印路径,用记忆化搜索实现

 

#include <cstdio>

#include <cstring>

#define N 550

int a[N],b[N],n;

bool g[N][N];

int dp[N],path[N];



void dfs(int i)

{

    if(dp[i]!=-1) return ;



    dp[i]=1;

    for(int j=1; j<=n; j++) if(g[i][j])  

    {

        dfs(j);

        if( dp[j]+1 > dp[i] )

        { dp[i]=dp[j]+1; path[i]=j; }

    }

    return ;

}



int main()

{

    while(scanf("%d",&n)!=EOF)

    {

        for(int i=1; i<=n; i++) scanf("%d%d",&a[i],&b[i]);

        memset(g,0,sizeof(g));

        for(int i=1; i<=n; i++)

            for(int j=1; j<=n; j++)

                if(a[i]<a[j] && b[j]<b[i]) //i能包含j

                    g[i][j]=1;



        memset(dp,-1,sizeof(dp));

        memset(path,-1,sizeof(path));



        int max=0,m=0;

        for(int i=1; i<=n; i++) //枚举所有点求出最长路

        {

            if(dp[i]==-1)

            {

                dp[i]=1;

                for(int j=1; j<=n; j++) if(g[i][j]) //i能包含j

                {

                    dfs(j);

                    if(dp[j]+1 > dp[i])

                    { dp[i]=dp[j]+1; path[i]=j; }

                }

            }

            if( dp[i]>max )

            { max=dp[i]; m=i;}

        }



        int s[N],top=0;

        printf("%d\n",max);

        while(m!=-1)

        { s[top++]=m; m=path[m]; }

        for(int i=top-1; i>=0; i--)

            if(i) printf("%d ",s[i]);

            else  printf("%d\n",s[i]);

    }

    return 0;

}

 

你可能感兴趣的:(IM)