草庐IT

动态规划刷题记录(1)

老菜鸟· 2023-09-02 原文

动态规划问题在这两年蓝桥杯频繁出现,它既是一个重点,也是一个难点。

1、整数拆分

 这道题目的思路其实很直接,基本上一眼就可以看出来这是完全背包问题的应用+一维优化。

整数N相当于是背包体积,2的幂相当于是物品体积,每种物品可以拿无数次,问你方案有多少种。数据范围已经给你了,我们可以确定最多用到2的20次方,因为2的21次方已经大于一百万了,于是我们先把2的前二十次方预处理。

接下来就是重点,我们定义集合f(i ,j)表示从前i个物品挑选使用,占用的体积为j的方案数,状态划分就是是否用了第i个物品?用了多少个?可能你没学过完全背包会看不懂我在说什么,背包问题作为动态规划的典型问题最好还是花时间学习

上代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define N 1000100

const int mod = 1e9;

int n ,p[N];
int f[N];

int main()
{
    cin >> n;

    int t = 1;
    for (int i = 0 ;i <= 21 ;i ++) p[i] = t ,t *= 2;

    f[0] = 1;
    for (int i = 0 ;i <= 21 ;i ++)
        for (int j = p[i] ;j <= n ;j ++)
            f[j] = (f[j] + f[j - p[i]]) % mod;

    cout << f[n];
    return 0;
}

2、最大的和

这道题目说白了就是让你在一行数中找到其中的两段,使这两段的和最大。这是一个动态规划问题,思路主要有两种:

(1)我们先来想想如果题目问你的是让你找到一个最大子段和,我们怎么解决?定义集合f(i)表示前i个数中的最大子段和,w[i]用来记录这n个数。那么以最大子段是否包含第i个数为集合划分依据:

     区间不包含w[i]: f[i] = f[i - 1];
    区间包含w[i]: f[i] = 以w[i - 1]结尾的最大连续区间和 + w[i];

那么很明显,我们缺少一个数据用来表示 以w[i - 1]结尾的最大连续区间和,所以我们再开一个区间h(i)用来记录以w[i]结尾的最大子段和。h(i)同样需要我们来递推:

        区间只包含w[i],也就是说a[i]一个数的和就大于了之前所有以w[i]结尾的子段和:h[i] = w[i];

        区间包含了w[i]: h[i] = h[i - 1] + w[i];

到这里我们就可以解决找到一个最大子段和的问题了,那么现在再想想题目的求两段最大子段和。我们完全可以正着推一遍,再反着来一遍,最后枚举中间点在哪就行了。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

#define N 1001000

int t ,f[N] ,h[N] ,g[N] ,w[N];

int main()
{
    cin >> t;
    while (t --)
    {
        int n;
        scanf("%d" ,&n);

        for (int i = 1 ;i <= n ; i ++) scanf("%d" ,&w[i]);//记录这n个数

        f[0] = g[0] = -1e9;//初始化数组,这里是个细节要注意,一般来说我们动态规划求最大值就需要初始化很小的数,求最小值就需要初始化一个很大的数。
        for (int i = 1 ;i <= n ;i ++)
        {
            h[i] = max(h[i - 1] ,0) + w[i];//其实就是h[i - 1] + w[i] 和 w[i]取最大值
            f[i] = max(f[i - 1] ,h[i]);//根据上面的递推公式
        }

        h[n + 1] = g[n + 1] = -1e9;//刚刚是1到n,现在我们n到1来一遍
        for (int i = n ;i >= 1 ;i --)
        {
            h[i] = max(h[i + 1] ,0) + w[i];
            g[i] = max(g[i + 1] ,h[i]);
        }

        int res = -1e9;
        for(int i = 1;i <= n;i ++) res = max(res, f[i] + g[i + 1]);//枚举断点,寻找最大值
        cout << res << endl;
    }

    return 0;
}

(2)第二种思路更好理解一点:f(i ,j ,0/1)表示考虑前 i个数,且已经选了 j个连续的子段,且第 i
个数是否在第 j 段中。

#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>

using namespace std;

#define N 50010

int f[N][3][2] ,a[N];

int main()
{
    int t;
    scanf("%d" ,&t);

    while (t --)
    {
        memset(f ,-0x3f ,sizeof(f));

        int n;
        scanf("%d" ,&n);

        f[0][0][0] = 0;
        for (int i = 1 ;i <= n ;i ++) scanf("%d" ,&a[i]);

        for (int i = 1 ;i <= n ; i ++)
        {
            for (int j = 0 ;j <= 2 ;j ++)
            {
                 f[i][j][1] = max(f[i - 1][j][1] + a[i] ,f[i][j][1]);//若选择第 i个数接在原先由第 i−1个数作为末尾的第 j段后面:
                 f[i][j][0] = max(max(f[i][j][1] ,f[i - 1][j][1]) ,f[i - 1][j][0]);//如果不选第i个数
                 if (j) f[i][j][1] = max(max(f[i - 1][j - 1][0] + a[i] ,f[i][j][1]) ,f[i - 1][j - 1][1] + a[i]);//如果第i个数单独开了一段
            }
        }

        cout << max(f[n][2][1] ,f[n][2][0]) << endl;
    } 
    return 0;

}

有关动态规划刷题记录(1)的更多相关文章

  1. ruby - 在 Ruby 中动态创建数组 - 2

    有没有办法在Ruby中动态创建数组?例如,假设我想遍历用户输入的书籍数组:books=gets.chomp用户输入:"TheGreatGatsby,CrimeandPunishment,Dracula,Fahrenheit451,PrideandPrejudice,SenseandSensibility,Slaughterhouse-Five,TheAdventuresofHuckleberryFinn"我把它变成一个数组:books_array=books.split(",")现在,对于用户输入的每一本书,我想用Ruby创建一个数组。伪代码来做到这一点:x=0books_array.

  2. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

  3. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

  4. ruby - 在 Ruby 中动态生成多维数组 - 2

    我正在尝试动态构建一个多维数组。我想要的基本上是这样的(为简单起见写出来):b=0test=[[]]test[b]这给了我错误:NoMethodError:undefinedmethod`test=[[],[],[]]而且它工作正常,但在我的实际使用中,我不会事先知道需要多少个数组。有一个更好的方法吗?谢谢 最佳答案 不需要像您正在使用的索引变量。只需将每个数组附加到您的test数组:irb>test=[]=>[]irb>test[["a","b","c"]]irb>test[["a","b","c"],["d","e","f"]]

  5. ruby-on-rails - 使用 gmaps4rails 动态加载谷歌地图标记 - 2

    如何只加载map边界内的标记gmaps4rails?当然,在平移和/或缩放后加载新的。与此直接相关的是,如何获取map的当前边界和缩放级别? 最佳答案 我是这样做的,我只在用户完成平移或缩放后替换标记,如果您需要不同的行为,请使用不同的事件监听器:在你看来(index.html.erb):{"zoom"=>15,"auto_adjust"=>false,"detect_location"=>true,"center_on_user"=>true}},false,true)%>在View的底部添加:functiongmaps4rail

  6. ruby - 动态方法链? - 2

    如何在对象上调用方法名称的嵌套哈希?例如,给定以下哈希:hash={:a=>{:b=>{:c=>:d}}}我想创建一个方法,给定上面的散列,执行以下操作:object.send(:a).send(:b).send(:c).send(:d)我的想法是我需要从一个未知的关联中获取一个特定的属性(这个方法不知道,但程序员知道)。我希望能够指定一个方法链来以嵌套哈希的形式检索该属性。例如:hash={:manufacturer=>{:addresses=>{:first=>:postal_code}}}car.execute_method_hash(hash)=>90210

  7. ruby - 如何使用 method_missing 动态声明方法? - 2

    我有一个ruby​​程序,我想接受用户创建的方法,并使用该名称创建一个新方法。我试过这个:defmethod_missing(meth,*args,&block)name=meth.to_sclass我收到以下错误:`define_method':interningemptystring(ArgumentError)in'method_missing'有什么想法吗?谢谢。编辑:我以不同的方式让它工作,但我仍然很好奇如何以这种方式做到这一点。这是我的代码:defmethod_missing(meth,*args,&block)Adder.class_evaldodefine_method

  8. ruby - 动态扩展现有方法或覆盖 ruby​​ 中的发送方法 - 2

    假设我们有A、B、C类。Adefself.inherited(sub)#metaprogramminggoeshere#takeclassthathasjustinheritedclassA#andforfooclassesinjectprepare_foo()as#firstlineofmethodthenrunrestofthecodeenddefprepare_foo#=>prepare_foo()neededhere#somecodeendendBprepare_foo()neededhere#somecodeendend如您所见,我正在尝试将foo_prepare()调用注入

  9. ruby - 使用 jbuilder 创建具有动态哈希键的 JSON - 2

    这里我想输出带有动态组名的json而不是单词组@tickets.eachdo|group,v|json.group{json.array!vdo|ticket|json.partial!'tickets/ticket',ticket:ticketend}end@ticket是这样的散列{a:[....],b:[.....]}我想要这样的输出{a:[.....],b:[....]} 最佳答案 感谢@AntarrByrd,这个问题有类似的答案:JBuilderdynamickeysformodelattributes使用上面的逻辑我已经

  10. ruby - 在 Rakefile 中动态生成 Rake 测试任务(基于现有的测试文件) - 2

    我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n

随机推荐