JSOI 2016 病毒感染 辅助Dp问题
原题链接:https://www.luogu.com.cn/problem/P5774
分析
直接看这道题,第一个困惑点,那个绝对值的比较是什么东西,根据数学知识,我们可以知道这个意思是k到i的距离小于k到j的距离,而路线是线性的,这就意味着当且仅当k在j的左边时才成立,不然总会有k-i>k-j,还不理解?看下图

如果K在K'的位置,那么K-i一定大于K-j吧,所以这个题的题意是只要从j往回走去治愈K,就必须把之前没治愈过的村庄也治愈了。
想到这里,状态就差不多出来了,定义DP[i]表示治愈前i个村庄的最小死亡数,下面考虑状态转移,对于JYY来说,每个村庄它都有两个选择,治愈or先去别的再走回来治愈,治愈的话很好弄,主要考虑的就是略过它的情况,这时候如果依次枚举K,效率应该是N^3,程序吃不消,3000的极限数据我们最少也要压到N^2左右,所以接下来考虑优化。
优化其实也挺简单的,主要有一点很恶心,下边再说。(从这里开始默认j在i的前边,请勿被上图迷惑)我们发现多出来的时间主要是用在了计算略过村庄再回来的死亡人数的计算,所以我们可以先考虑预处理出从j到i再从i到j然后又回到i这一过程中最少的死亡数,于是定义g[i][j]含义为上述的来辅助我们的DP。我还是补一张图吧……把我自己绕懵了

看了这张图我相信你就明白了g数组的含义,接下来考虑如何求解g数组,初始的话g[i][i]肯定是为0的,所以转移都应该从这个位置开始,即倒序,那么怎么转移呢,接下来就是很恶心的一个地方,计算经过的天数!很多题解里都没写到这个,这里详细计算一下。
对于g[i][j],同样分两种情况讨论,救助或是略过,不管是救助还是略过,都避免不了经过一个区间,就是j+1到i,所以这里可以分而治之,把j和j+1到i这两个分开,g[i][j]的转移中应该需要有g[i][j+1],这里又启示我们进行倒序循环,同样,不管救助j还是略过,从j走到j+1的这一天里,区间j+1到i这一段的村庄都会死亡(为村民默哀?)所以答案累加Sum(j+1,i)这个可以由前缀和O(1)求出,到了点j+1后,j+1到i的死亡人数就已经被记在了g[i][j+1]里,所以可以不用考虑,这是两种情况所共同具有的死亡人数,下面对两种情况分开讨论,如果救治j的人,那么区间j+1,i的村民就要多死一天,即Sum(j+1,i),不救治呢?因为同样的我们跑路的代价都记录在了g[i][j+1]里边,所以不救治的代价就是在这段时间里j村死亡的人数,你可能问,别的村难道没有死亡的吗?当然可能会有,但我们已经记录了,所以这里不需要再次加入,首先算一下从j跑到i再跑回来所需要的时间,这里举个例子,从4到5要1天,4到6要2天,4到7要3天,所以显然跑路时j村死亡的人是2*(i-j)*a[j],2是跑了两遍,i-j是刚刚推出来的,a[j]是j村日死亡人数,那只有这些吗?当然不是,这只是跑路的代价,根据定义和题意,j+1到i这些村庄均被治愈且均在略过j后被治愈,所以一个村庄一天,一共就是(i-(j+1)+1)*a[j]天,于是我们的g[i][j]就有了转移方程
g[i][j]=g[i][j+1]+Sum(j+1,i)+min(3*(i-j)*a[j],Sum(j+1,i))
辅助进行转移的方程有了之后我们就可以进行dp的转移了,没错,下边还有很恶心的算时间。
对于每前i个村庄,都不可能直接求出他的最小值,所以要枚举中间点j,即我治愈了前j个村庄,但是j+1被略过了,所以j+1的治愈是从j+1走到i再走回来时才被治愈,这一段的代价就是g[i][j+1],治愈前j个的代价为dp[j],直接累加答案即可,那么最硬核的东西就是i+1到n的这段区间,因为在当前阶段,这段区间内的人是不可能被治愈的,所以一天内的死亡人数是Sum(i+1,n),天数呢?根据我之前所推导的,从j+1到i之间反复横跳一来一回一来需要天数3*(i-(j+1)),治愈区间j+1到i需要时间(i-(j+1)+1),这里不要忽略了一个地方,就是从j跑路跑到j+1时还有一天,所以总天数就是3*(i-(j+1))+i-(j+1)+1+1,乘上每天死亡的人数就是最后的代价,累加答案。
至此,这道省选题就落下了帷幕……什么?你问我最后转移的时候没考虑略过i就是一路向右的情况?怎么可能,当我枚举到j=i-1的时候,就相当于转移了这种情况,是吧,所以这个算法是没有问题的,时间复杂度大致为O(n^2)可以A掉
Tips::如果你实在看不懂时间怎么算的请拿起笔自己模拟一下吧,很快就能懂,我也尽力了。
#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
const int N=3e3+;
ll s[N],g[N][N],dp[N],a[N];
ll Sum(int l,int r){
return s[r]-s[l-];
}
int main(){
int n;
cin>>n;
for(int i=;i<=n;i++){
cin>>s[i];a[i]=s[i];s[i]+=s[i-];
}
for(int i=;i<=n;i++)
for(int j=i-;j;j--)
g[i][j]=g[i][j+]+Sum(j+,i)+min(3LL*(i-j)*a[j],Sum(j+,i));
memset(dp,0x3f,sizeof dp);
dp[]=;
for(int i=;i<=n;i++)
for(int j=;j<i;j++)
dp[i]=min(dp[i],dp[j]+g[i][j+]+Sum(i+,n)*((i-(j+))*+i-(j+)+));
cout<<dp[n];
}
JSOI 2016 病毒感染 辅助Dp问题的更多相关文章
- BZOJ4856 病毒感染 [Jsoi2016] dp
正解:区间dp+辅助dp 解题报告: 先放个传送门qwq 然后这题,又是一道看不懂题目的玩意儿:( 大概是语文太差 那就先解释下 其实只是一个点比较难明白就是它港 "假设JYY 进入i村庄并 ...
- [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)
[BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...
- JSOI 2016 扭动的字符串
JSOI 2016 扭动的字符串 题面描述 给出两个长度为\(n\)的字符串\(A,B\) \(S(i,j,k)\)表示把\(A\)中的\([i,j]\)和\(B\)中的\([j,k]\)拼接起来的字 ...
- [JSOI 2016] 最佳团体(树形背包+01分数规划)
4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2003 Solved: 790[Submit][Statu ...
- BZOJ4856 JSOI2016 病毒感染 区间DP
传送门 原Word文档 题意:太长不给 这种题目一看就是区间DP 设$f_i$表示治愈了前$i$个村子的时候最少死了多少村民,又设前缀和为$sum_i$,通过枚举折返时最后经过的村子$j$,并且提前计 ...
- 解题:JSOI 2016 最佳团体
题面 0/1分数规划+树形背包检查 要求$\frac{\sum P_i}{\sum S_i}的最大值,$按照0/1分数规划的做法,二分一个mid之后把式子化成$\sum P_i=\sum S_i*mi ...
- BZOJ 4521 CQOI 2016 手机号码 数位DP
4521: [Cqoi2016]手机号码 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 539 Solved: 325[Submit][Status ...
- 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) F 区间dp
Problem F Removal GameBobby Roberts is totally bored in his algorithms class, so he’s developed a li ...
- [JSOI 2016] 最佳团体
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4753 [算法] 很明显的分数规划 可以用树形动态规划(树形背包)检验答案 时间复杂度 ...
随机推荐
- metrics模块
class sklearn.metrics 方法 1.分类问题的度量 metrics.accuracy_score metrics.auc metrics.f1_score metrics.preci ...
- Mysql报错:Authentication .....Reading from the stream has failed
连接Mysql5.7版本的数据库出现报错:Authentication to host '171.13.164.***' for user 'root' using method 'mysql_nat ...
- 阿里sentinel说明及使用
使用说明 如果只是为了让使 用Sentinel 的限流功能,只需要引入相关的jar包依赖. 添加依赖 添加相关模块的Adapter Sentinel为每个构建项目的各个组件都打包成了相应的Adapte ...
- @常见的远程服务器连接工具:Xshell与secureCRT的比较!!!(对于刚接触的测试小白很有帮助哦)
现在比较受欢迎的终端模拟器软件当属xshell和securecrt了. XShell绝对首选,免费版也没什么限制,随便改字体随便改颜色随便改大小随便改字符集,多窗口,也比较小巧,而SecureCRT界 ...
- Chromium的无锁线程模型C++代码示例
引言 作者:程序员bingo,主要关注客户端架构设计.性能优化.崩溃处理,有多年的Chromium浏览器开发经验. 多线程一直是软件开发中最容易出问题的环节,很多的崩溃.卡死问题都与多线程有关.在常用 ...
- redis 出现(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details
如果在ubuntu安装的redis含端口使用,但是某些时候常常出现 (error) MISCONF Redis is configured to save RDB snapshots, but is ...
- Flink系列之1.10版流式SQL应用
随着Flink 1.10的发布,对SQL的支持也非常强大.Flink 还提供了 MySql, Hive,ES, Kafka等连接器Connector,所以使用起来非常方便. 接下来咱们针对构建流式SQ ...
- 【Python】2.12学习笔记 变量
变量 关于变量我有一个不能理解的,关于全局变量作用域与地址的问题,学函数的时候我可能会搞懂它并且写下来 另外,其实昨天说的是有些不准确的,\(Python\)里的变量不是不用声明类型,只是声明方式特殊 ...
- 解决使用 el-table 中使用多选框 Checkbox 不刷新问题
问题 在 el-table 中使用 Checkbox 仅作为展示时,v-model 双向绑定就变得不那么适用了,这时候我们会使用 checked 属性来代替v-model. 问题来了当使用 filte ...
- 阿里云加Picgo或MPic搭建最豪横的图床
阿里云加Picgo或MPic搭建最豪横的图床 首先解释一下什么是图床,图床其实就是提供图片存储的服务器. 对于自建博客来说,由于各种原因的限制(比如穷...)可能无法购买存储空间比较大的VPS. 而对 ...