原题链接: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问题的更多相关文章

  1. BZOJ4856 病毒感染 [Jsoi2016] dp

    正解:区间dp+辅助dp 解题报告: 先放个传送门qwq 然后这题,又是一道看不懂题目的玩意儿:( 大概是语文太差 那就先解释下 其实只是一个点比较难明白就是它港 "假设JYY 进入i村庄并 ...

  2. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

  3. JSOI 2016 扭动的字符串

    JSOI 2016 扭动的字符串 题面描述 给出两个长度为\(n\)的字符串\(A,B\) \(S(i,j,k)\)表示把\(A\)中的\([i,j]\)和\(B\)中的\([j,k]\)拼接起来的字 ...

  4. [JSOI 2016] 最佳团体(树形背包+01分数规划)

    4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2003  Solved: 790[Submit][Statu ...

  5. BZOJ4856 JSOI2016 病毒感染 区间DP

    传送门 原Word文档 题意:太长不给 这种题目一看就是区间DP 设$f_i$表示治愈了前$i$个村子的时候最少死了多少村民,又设前缀和为$sum_i$,通过枚举折返时最后经过的村子$j$,并且提前计 ...

  6. 解题:JSOI 2016 最佳团体

    题面 0/1分数规划+树形背包检查 要求$\frac{\sum P_i}{\sum S_i}的最大值,$按照0/1分数规划的做法,二分一个mid之后把式子化成$\sum P_i=\sum S_i*mi ...

  7. BZOJ 4521 CQOI 2016 手机号码 数位DP

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 539  Solved: 325[Submit][Status ...

  8. 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 ...

  9. [JSOI 2016] 最佳团体

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4753 [算法] 很明显的分数规划 可以用树形动态规划(树形背包)检验答案 时间复杂度 ...

随机推荐

  1. cssy元素居中的方法有哪些?

    css的元素居中 各位小伙伴们在努力写网页的时候有没有遇到过这样的一个问题呢? 在写的时候发现他不居中,可是要分分钟逼死强迫症的啊! 别急,我来啦 哈哈哈 今天就带来三种css的元素居中的方法 第一种 ...

  2. Python:turtle库的使用及图形绘制

    目录 一.绘制一个八边形 二.绘制一个八角图形 三.简述问题 四.循环程序设计 五.绘制一个自己喜欢的图形 一.绘制一个八边形 使用turtle库,绘制一个八边形 代码: from turtle im ...

  3. 爬虫(二)requests 登陆某检索网站

    1 import requests import os from PIL import Image import pytesseract import re rootUrl = xxx # 构建登录页 ...

  4. Roma - Facebook工具链大一统

    什么是roma roma,中文名罗马,是Facebook的rn团队的产出,是一个试验性质的javascript工具链,集编译,linter,格式化,打包,测试等等于一体.目标是成为一个处理javasc ...

  5. 前端每日实战:55# 视频演示如何用纯 CSS 创作一个太阳、地球、月亮的运转模型

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/RJjQYY 可交互视频 此视频是可 ...

  6. Linux学习5-安装mysql

    前言 今天我们来学习一下如何在Linux下安装mysql 一:准备安装包 可以从http://www.mysql.com/downloads/官方网站下载到最新版本,本次安装的版本是mysql-5.7 ...

  7. javascript的装饰者模式Decorator

    刚开始看这段代码有点绕,现在回过头来看,so easy! Function.prototype.before = function(beforefn){ var _self = this; retur ...

  8. PTP从时钟授时模块应用及介绍

    PTP从时钟授时模块应用及介绍 随着网络技术的不断进步和发展,NTP网络时间协议已经满不了一些精密设备和仪器的精度要求,这时就需要精度更高的PTP协议,PTP协议是一种应用于分布式测量和控制系统中的精 ...

  9. JS中的reduce()详解

    reduce()作为一个循环使用.接收四个参数:初始值(上一次返回值),当前元素值,当前元素下标,原数组. 应用  作为累加器使用 var a=[4,5,6,7,8] //item代表一次回调的值 初 ...

  10. SQLi-Labs之1~6关 - 常规注入与盲注

    年初五 财神入 第一关 联合注入 1.准备 2.加'截断 3.order by 判断查询列数 4.同上 5.联合查询判断字段位置 6.查数据库名 7.1 查表名 7.2 查列名 8.查数据 第二关 不 ...