BadNeighbors - 2004 TCCC Round 4

本文介绍了一个基于动态规划解决的问题——如何在遵循特定规则的情况下从一系列捐款中获得最大总额。在一个环形排列的城镇中,每个居民愿意捐款一定数额,但拒绝与邻居共同捐赠。文章详细解释了动态规划算法的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



Problem Statement

    
The old song declares "Go ahead and hate your neighbor", and the residents of Onetinville have taken those words to heart. Every resident hates his next-door neighbors on both sides. Nobody is willing to live farther away from the town's well than his neighbors, so the town has been arranged in a big circle around the well. Unfortunately, the town's well is in disrepair and needs to be restored. You have been hired to collect donations for the Save Our Well fund.

Each of the town's residents is willing to donate a certain amount, as specified in the int[] donations, which is listed in clockwise order around the well. However, nobody is willing to contribute to a fund to which his neighbor has also contributed. Next-door neighbors are always listed consecutively in donations, except that the first and last entries in donations are also for next-door neighbors. You must calculate and return the maximum amount of donations that can be collected.


动态规划。

状态:

d[i]表示前i个donation中以num[i]为结尾的最大的满足限制条件的donation序列和。

状态转移:

要想求d[i],就把i-1(因为不能相邻)前面的各个子序列的的d[j](0<=j<i-1)加上当前的donation值num[i],然后取最大就是当前的状态d[i]。这里要注意的是,最后一个数和第一个数也不能相邻,故保存一个是否以第一个数开头的标记数组label[]。当i等于n-1时要判断label[j]是否为1,如果为1,则continue。每次更新d[i]时也更新label[i]。


int maxDonations(int num[], int n)
{
    int *d = new int[n];
    int *label = new int[n];

    int max_don = 0;
    label[0] = 1;
    for(int i = 0; i < n; i++)
    {
        d[i] = num[i];
        for(int j = 0; j < i - 1; j++)
        {
            if(i == n-1)
            {
                if(label[j] == 1)
                    continue;
            }
            if(d[j] + num[i] > d[i])
            {
                d[i] = d[j] + num[i];
                if(label[j] == 1)
                    label[i] = 1;
                else
                    label[i] = 0;
            }
        }
        if(d[i] > max_don)
            max_don = d[i];
    }
    return max_don;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值