zoj3160Couples

zoj3160Couples

In the world ofknowledge, so many new words appear on the internet. A special one is"8g", a kind of special relationship between two persons. (If youwant to know more words, just turn to a search engine.)

You aregiven n people and the "8g"relationships between them. Now they are standing in one line and the followingthings may happen.
1. If two persons with "8g" relationship stands next to each other,they may run away and never come back.
2. If the people between the ith person andthe jth person all ran away, now the ithone and the jth one areconsidered to be next to each other.

According to therules, when a person has "8g" relationships with the two persons inhis/her two sides. He/She can run with either one. So there may be many ways inwhich people could run.

So, for allpossibility, we want to know the maximum number of persons that can run intotal.

Input

The first line ofeach case will contain two integers n(2 <= n <=300) and m, indicating the number of persons and thenumber of "8g" relationships(Persons are indexed from 0 to n - 1).Next m lines contains two integers a and b, meaning thatthere is a "8g" relationship between a and b. Then followed bya line containing a permutation of 0 to n - 1, meaning the arrangement of the npersons. Proccess to the end of file.

Output

For each case,print one line containing the maximum number of people that can run in total.

Sample Input

4 2

0 3

1 2

0 1 2 3

Sample Output

4



         【分析】n个人,其中有若干个人有关系,若有关系的两人站在一起(相邻),他们就会离开,他们旁边的两人就变成了相邻的了,求可以走掉的最大人数。

         区间DP

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

int vis[ 301 ][ 301];

int data[ 301 ];

int dp[ 301 ][ 301 ];

 

int main()

{

    int n,m,a,b;

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

        memset( vis,0,sizeof( vis ) );

        for ( int i = 1 ; i <= m ; ++ i ) {

           scanf("%d%d",&a,&b);

            vis[a][b] = 1;

            vis[b][a] = 1;

        }

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

            scanf("%d",&data[i]);

 

        memset(dp,0,sizeof(dp));

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

            if (vis[data[i]][data[i+1]])

                dp[i][i+1] = 2;

 

        for (int i = n-2;i >= 1;i--)

        for (int j = i+2;j <= n;j++)

            if (dp[i+1][j-1] == j-i-1&& vis[data[i]][data[j]])

                dp[i][j] = j-i+1;

            else {

                for ( int k = i ; k < j ; ++k )

                    if ( dp[i][j] < dp[i][k]+ dp[k+1][j] )

                        dp[i][j] = dp[i][k] +dp[k+1][j];

            }

 

        printf("%d\n",dp[1][n]);

    }

    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值