[蒟蒻实验室]Ep.1背包退火!

[蒟蒻实验室]Ep.1背包退火!

· FBI Warning

· 新算法:背包退火!

· 本文所包含的思路来自于NCC79601巨佬的启迪Orz

·算法剖析

简单来讲,背包退火就是用模拟退火的思路解决某些类型的背包问题,继承了模拟退火的玄学复杂度,也继承了它的不稳定性,所以能够有效地解决大背包问题的TLE问题。这个算法能够把数十行的代码优化部分转移为 洗把脸 调参的问题。

例题 :LuoGuP1049【装箱问题】

有一个箱子容量为V,同时有n个物品,每个物品有一个体积vi。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

·算法过程

首先就是模拟退火的随机设置自然就是把随机数种子设置好,别忘了先洗脸,然后通过模拟退火原理设置好转移概率表达式:

1 bool accept(int del)
2 {
3     return ((del>0)||exp(-del/T) > (double)rand()/RAND_MAX);
4 } //转移概率表达式

然鹅蒟蒻的我很难解释清楚为什么随着T的减小他接受更劣解的概率会越来越小,只知道利用这个概率是e^(-dE/kT)。

使用这个概率从而达到刚开始退火,跳出当前最优解的概率大,而当靠近答案时跳出正确答案的可能性又逐渐减小。如有不懂请挪步模拟退火详解

·偏移过程

这就是上述问题的用武之地了:以一定的概率不选当前最优解中的那个物品,从而衍生出另一种方案,如果比刚刚的更好,那么说明运气很好,跳到了一个更优解范围附近

 1 if(accept(dE))
 2         {//以上述概率发生转移
 3             if(vis[a])
 4             {
 5                 vis[a] = false;
 6                 tot -= v[a];
 7             }//在当前物品已选的情况下放弃选用当前物品
 8             else
 9             {
10                 if(tot + v[a] > V)
11                 {
12                     continue;
13                 }
14                 vis[a] = true;
15                 tot += v[a];
16             }//在当前物品未选的情况下尝试选用当前物品
17         }

·退火步骤

while(T > 1e-14) {
        ans=max(ans,tot); //维护最优答案,以防非酋情况发生
        a = rd; //进行随机
        int dE = v[a];
        if(vis[a])
        {
            dE *= -1; //产生能量差
        }
        if(accept(dE))
        {//发生转移
            if(vis[a])
            {
                vis[a] = false;
                tot -= v[a];
            }
            else
            {
                if(tot + v[a] > V)
                {
                    continue;
                }
                vis[a] = true;
                tot += v[a];
            }
        }
        T *= delta; //降温
    }

该过程通过降温系数delta对初温为T的物体降温,直到物体温度冷却接近0。但是不能直接将tot作为答案输出,否则没洗脸的话可能会出现跳到了较劣解的情况。

退火的一些小技巧

1. 降温系数用0.99789(玄学参数)

2. 初温设置为1926(玄学参数)

3. 退火的转移概率计算式:e^(-dE/kT)

(del>0)||exp(-del/T) > (double)rand()/RAND_MAX

4.最低温不要调的太低,不然妥妥的TLE

5.交一次不行说明rp不够你的时间不好,原代码再交一次也许 就行了呢

6.别忘了洗脸rp++

番外篇:论欧皇的养成

iewqufhiwefdiweduiqwediuqedwedjewui

(被某个非酋网友摁在键盘上打/笑哭)

这是某个没洗脸的基佬的↑

这是我的↓

溜了溜了……

原文地址:https://www.cnblogs.com/firstfan/p/10125987.html

时间: 2024-10-14 19:32:29

[蒟蒻实验室]Ep.1背包退火!的相关文章

蒟蒻ACMer回忆录 · 一段弱校ACM的奋斗史

三年半的ACM生涯终于迎来了终点,退役之时,感慨万分,故写此文以纪念逝去的时光,那些为ACM拼搏的日子,那段弱校ACM的奋斗史. 三年半的ACM生涯,窝见证了CUMT从打铁到铜牌的突破,又见证了从铜牌到银牌的突破:见证了集训队员从3人发展到10余人,又见证了ACM实验室的落实. 三年半的ACM生涯,窝经历了太多,有Accepted时的欢笑,有Wrong Answer时的沮丧,有Time Limit Exceeded时的无奈,有Runtime Error时的尴尬,有打铁的失落,有拿牌的惊喜. 13

算法描述》LCA两三事(蒟蒻向)

LCA是图论中常用的解决树形结构子问题的工具,这一问题一般需要用一个简短的子函数直接解决,但是这对于广大蒟蒻们仍然是一个不小的问题. LCA是指在树形结构中两点的最近公共祖先,对于这个问题,直接向上找事最直接的方法,但同时时间复杂度和数据给出的生成树的层数有关,最优情况是logN级别的,但是如果数据给出的是一条链就GG了,所以要用更优的方法写,一般来说,用的是log2N的操作,最糟糕的复杂度也是logN级别的,那如何实现这一过程捏,我这里有两种方法,和大家分享 第一种:树上倍增 具体方法是对于已

bzoj 4636: 蒟蒻的数列

4636: 蒟蒻的数列 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一行一个整数N,然后有N行,每行三个正整数a.b.k. N<=40000 , a.b.k<=10^9 Output 一个数,数列中所有元素的和 Sample Input 4 2 5

蒟蒻的第一篇博文

先刷一波存在感... 据说维护Blog可以作为积累然后就决定开一波Blog=.= 本来想用Hexo Framework加上GitHub Pages做一个Blog来着(因为GitHub比较Geek嘛) 然后折腾了半天搞了个NexT Theme感觉异常地漂亮 然后Commit上了GitHub还写了几篇测试文章自我感觉良好 然后调整了一发文件夹结构因为我总是要移动工作区 然后折腾了一段时间感觉这个Blog估计可以使了 然后... 然后突然发现Hexo Framework构造的是一大坨静态页面没法加载数

【BZOJ】4636: 蒟蒻的数列

4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 145  Solved: 71[Submit][Status][Discuss] Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一行

BZOJ3786 星系探索 蒟蒻出题人给跪

本蒟蒻闲得蛋疼于是在BZOJ上加了一道水题,果然被瞬间水过... 只能说本蒟蒻实在是太弱了. Q:你为什么要写这篇博客? A:我只是为了水经验233.... 正常向的数据.题解.标程请自行传送下面的云盘... http://pan.baidu.com/s/1qWsMHM8 吐槽: 为什么本地不开O2 10s在OJ上开O2 还需要20+s啊!!!我本来不想卡常数好不好. 因为这个原因用数组实现数据结构被卡的请见谅...现在是40s应该卡不掉了. 另外如果发现自己被卡掉请重交一次.原因不解释. 为什

论蒟蒻的自我修养

作为一个蒟蒻,离开大神还有很大一段距离(更不用说神犇了).作为一个想成为SB的SX,自我修养是及其重要的.即使初三老师丧心病狂,也不能放弃这条路恩! 计划: 恩不去MO但是学习他们的那些书~~毕竟数学渣 = ^ = 然后是数据结构...我最弱的一块辣 然后是算法...我也不强 解题思路 啊啊啊!!!差得要命!!! 写程序 啊啊啊!!要死辣!! 所以要多写多练撒!! 要开始刷题了撒!! BZOJ的题目都不会啊!!要死了撒! 估计学一下MO还是有好处的..至少OI MO不分家~~MO主要是数论和排列

博主自传——蒟蒻的OI之路

博主来自河北石家庄市第二中学,现在读高二,主攻信息学竞赛(其实并没有学习其他学科竞赛). NOIP中人品大爆发,使劲挤进河北省一等奖队伍,侥幸留在竞赛团队中(差点就淘汰出局啦). 关于我的ID,YOUSIKI,就是那四个平假名,没有什么实际意义.若搜到日本某艺人,和我无关. NOIP前主要活跃在PekingUniversityOnlineJudge(不知道拼错木有),现在主要活跃在Lydsy(小伙伴们都叫他BZOJ). 在各个OJ上基本都有号(有大号也有小号),ID都是YOUSIKI.Tyvj,

【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss] Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一