zoj3161 DP

将自己历史的AC共享

zoj3161 DP题

dp[i] = max( min(dp[j-1]+dp[i-j],dp[j]+dp[i-j-1]),1<=j< i )

//1767788 2009-02-20 10:53:25 Accepted  3161 C++ 100 1176 green tea 
#include <cstdio>
#include <algorithm>
using namespace std;

//当确定出一个情侣的序列时,会员们会尽最大的努力使跑掉的人最多。问题是帮管家确定一个序列,使留下来的人最多。
//假设有 i 个连续的人,每相邻两个都有 8g 关系,管家给出一个序列使留下最多 dp[i] 个人
//管家给出的第一个序列可能是 (j, j + 1) 这时第 j 个人或许第 j+1 个人会跑掉. 留下的人为 dp[j-1] + dp[i-j]
//或dp[j] + dp[i-j-1]. 取其中小的一个。枚举 j 的位置 可得到 dp[i] 的最大值。

int n, m;

int a[505][505], dp[505], f[505];

void Dp() {
    int i, j, temp;
    dp[0] = 0;
    dp[1] = dp[2] = dp[3] = 1;
    for ( i = 4; i <= 500; ++i ) {
        dp[i] = 0;
        for ( j = 1; j < i; ++j ) {
            temp = min(dp[j-1]+dp[i-j], dp[j]+dp[i-j-1]);
            if ( temp > dp[i] )    dp[i] = temp;
        }
    }
}

int main()
{
    int i;
    while ( scanf("%d%d", &n, &m) != EOF ) {
        int s, e;
        Dp();
        memset(a, 0, sizeof(a));
        memset(f, 0, sizeof(f));
        for ( i = 0; i < m; ++i ) {
            scanf("%d%d", &s, &e);
            a[s][e] = a[e][s] = 1;
        }
        int res = 0, k = 0;
        for ( i = 0; i < n-1; ++i ) {
            if ( k == 0 && a[i][i+1] == 1 ) { k+=2;f[i]=f[i+1]=1; }
            else if ( a[i][i+1] == 1 )    { k++;f[i]=f[i+1]=1; }
            else {
                res += dp[k];
                k = 0;
            }
        }
        res += dp[k];
        for ( i = 0; i < n; ++i )
            if ( f[i] == 0 )    res++;
        printf("%d\n", res);
    }
    return 0;
}

如觉得还有问题 可参考其他相关文章
zoj3161 其他1
zoj3161 其他2
zoj3161 其他3
zoj3161 其他1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值