【动态规划初级】 BadNeighbors

目录
  • 最大连续序列和
  • 不连续序列的最大和
1.最大连续序列和是指所有连续子序列元素和最大的那个。
状态转移方程
sum[i]=max(sum[i-1]+a[i],a[i])

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
    freopen("in.txt","r",stdin);
    int n;

    while(cin>>n)
    {
        int a[n];
        int sum=0;
        int  maxsum=0;
        for(int i=0; i<n; i++)
        {
            cin>>a[i];
            sum+=a[i];
            if(sum>maxsum)maxsum=sum;
            if(sum<0)sum=0;
        }
        cout<<maxsum<<endl;
    }
}
测试用例:
6
-2 11 -4 13 -5 -2
5
1 -2 3 -1 7
结果
20
9

2.不连续序列的最大和应用

Problem Statement for BadNeighbors

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.

 

Definition

    
Class:BadNeighbors
Method:maxDonations
Parameters:int[]
Returns:int
Method signature:int maxDonations(int[] donations)
(be sure your method is public)
    
 

Constraints

-donations contains between 2 and 40 elements, inclusive.
-Each element in donations is between 1 and 1000, inclusive.
 

Examples

0)
    
{ 10, 3, 2, 5, 7, 8 }
Returns: 19
The maximum donation is 19, achieved by 10+2+7. It would be better to take 10+5+8 except that the 10 and 8 donations are from neighbors.
1)
    
{ 11, 15 }
Returns: 15
2)
    
{ 7, 7, 7, 7, 7, 7, 7 }
Returns: 21
3)
    
{ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }
Returns: 16
4)
    
{ 94, 40, 49, 65, 21, 21, 106, 80, 92, 81, 679, 4, 61, 
  6, 237, 12, 72, 74, 29, 95, 265, 35, 47, 1, 61, 397,
  52, 72, 37, 51, 1, 81, 45, 435, 7, 36, 57, 86, 81, 72 }
Returns: 2926

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2010, TopCoder, Inc. All rights reserved.


 
看题看不懂题意,看测试用例才猜出,即围成了一个圈,相邻的不捐款,求最大捐款数。
因为n个数围成了一个圈,为了避免第一个数和最后一个数相邻,问题就转化成了
求前n-1个数和后n-1个数的不连续序列的最大和。
下标从0开始,即求max(donations[0...n-1],donations[1...n-2])这样必不会出现首尾相连的情况,满足条件。


#include <iostream>
#include<stdio.h>
using namespace std;
#define LEN 100
int donations[LEN];
int sum[LEN];
int maxDonations(int n)
{

    for(int i=0;i<n;i++){
        sum[i]=donations[i];
    }
     int maxsum1=sum[0],maxsum2=sum[1];
    //0...n-2
    for(int i=0;i<n-1;i++){
        for(int j=0;j<i-1;j++){
            if(sum[j]+donations[i]>sum[i])
                sum[i]=sum[j]+donations[i];
            if(sum[i]>maxsum1)maxsum1=sum[i];
        }
    }
      for(int i=0;i<n;i++){
        sum[i]=donations[i];
    }
    //1...n-1
      for(int i=1;i<n;i++){
        for(int j=1;j<i-1;j++){
            if(sum[j]+donations[i]>sum[i])
                sum[i]=sum[j]+donations[i];
            if(sum[i]>maxsum2)maxsum2=sum[i];
        }
    }

    return maxsum1>maxsum2?maxsum1:maxsum2;
}

int main()
{
    int n;
    freopen("in.txt","r",stdin);
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
        {
            cin>>donations[i];
        }
        cout<<maxDonations(n)<<endl;
    }
    return 0;
}
















转载于:https://www.cnblogs.com/zhaokongnuan/p/e379e4feb641bbe2cde3934eca882e5f.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值