文章

18

粉丝

181

获赞

53

访问

91.1k

头像
1172 最大序列合 清华/兰大2019年机试
推荐阅读
P1172 清华大学/兰州大学2019机试
发布于2022年7月19日 11:57
阅读数 4.5k

这题归于动态规划,但是我之前怎么看都觉得是贪心

今天想通了,可以从两种不同的角度来看:

设dp[i]是以下标为i的元素为结尾的序列 的最大合值

  1. dp角度:
    1. 遍历到第i个元素时,两种选择:要么选择第i个元素(dp[i-1]+list[i]),要么不选(之前的序列断开,重新开始计数)(list[i]),取最大值
    2. 状态转移方程:
      dp[i]=max( dp[i-1]+list[i] , list[i] );
    3. 最后再求出dp[n]中的最大值
  2. 贪心角度:
    1. 如果之前的序列合为负值,则说明对之后的序列合没有贡献,就舍弃。
    2. 如果之前的序列合为正值,那么加上肯定是不亏的
    3. 代码:
      if (dp[i-1]<0) dp[i]=list[i];
      else dp[i]=dp[i-1]+list[i];
    4. 最后再求出dp[n]中的最大值

 

两种方法的代码实际上是一样的,只是说换个不同的写法,理解起来就方便很多了。

以下几点需要注意:

  • 题目规定了数值的范围 结果序列和在范围(-2^63,2^63-1)以内。所以定义变量时注意使用long long int。
  • 这里使用了0xc0c0c0c0无穷小来作为res的初始值,但是结果溢出,所以换成了-99999,希望大佬指出原因!

代码如下:

#include <bits/stdc++.h>

using namespace std;

#define MIN 0xc0c0c0c0; //无穷小

int main()
{
    int n;
    while (cin >> n)
    {
        long long int list[n];
        //输入
        for (int i = 0; i < n; i++)
        {

            cin >> list[i];
        }
        //求解
        long long int dp[n];
        dp...
登录查看完整内容


登录后发布评论

暂无评论,来抢沙发