题目描述

JOSI 的边陲小镇爆发了严重的 Jebola 病毒疫情,大批群众感染生命垂危。计算机科学家 JYY 采用最新的算法紧急研制出了 Jebola 疫苗,并火速前往灾区救治患者。

一共有 NN 个小镇爆发了 Jebola 疫情。这些小镇由于地处边陲,仅仅通过一条长直公路连接。方便起见我们将这些小镇按照公路连接顺序由 11 编号到 NN。JYY 会在第一天一早抵达 11 号小镇。

一开始在 ii 号小镇,有 a_iai​ 名患者感染了 Jebola 病毒。

每一天 JYY 可以选择:

  1. 花费一天时间彻底治愈 JYY 目前所在的村庄的所有 Jebola 患者。这一天不会有任何患者死去;
  2. 花费一天的时间前往一个相邻的村庄。

当一天开始时,如果一个村庄里有 kk 个 Jebola 患者,那么这一天结束时,这 kk 个患者会感染另外 kk 个这个村子里的健康村民并死去。所以对于 ii 号村庄,只要这个村庄没有被 JYY 彻底消灭疫情,那么每一天都会有 a_iai​ 个村民死去。

JYY 希望采用措施使得疫情被整体消灭时,总共死去的村民数量尽量少。

为了达成这一目标,JYY 有时会选择抵达一个村庄但是并不对村民进行施救。这样的行为如果不加限制,往往会造成更加严重的后果。

试想这样的情形:假设当 JYY 第一次抵达村庄 ii,未作救治并直接前往了另一个村庄。那么由于 ii 村庄的人们求生心切,一旦当 JYY 朝向靠近 ii 村庄的方向前行时,ii 村庄的村民就会以为 JYY 是来救他们了,而产生巨大的期望。之后倘若 JYY 再次掉头朝着远离 ii 村庄的方向行进,那么 ii 村庄的村民就会因为巨大的失落而产生绝望的情绪。

为了避免这种情况,JYY 对他的行程做了如下规定:

假设 JYY 进入 ii 村庄并在第二天立即离开(村庄 ii 的疫情并未治愈)。如果在之后的某一天,JYY 从村庄 jj 前往村庄 kk,并满足 |k-i| \lt |k-j|∣k−i∣<∣k−j∣。那么在之后的日子里 JYY 只能朝着 ii 村庄前进直到抵达 ii 村庄并立即治愈该村的患者。在前往 ii 村庄的过程中,JYY 可以选择将途经村庄的疫情治愈。

比如,如果 JYY 有如下行程:

第一天:从村庄 11 前往村庄 22;

第二天:从村庄 22 前往村庄 33;

第三天:治愈村庄 33;

第四天:前往村庄 22。

此时 JYY 对于之后三天的行程只有唯一一种选择:

第五天:治愈村庄 22;

第六天:前往村庄 11;

第七天:治愈村庄 11。

JYY 想知道在治愈所有村庄之前,至少会有多少村民因 Jebola 死去。

输入格式

输入第一行包含一个正整数 NN;

接下来一行包含 NN 个整数,分别为 a_1,a_2,...,a_Na1​,a2​,...,aN​。

输出格式

输出一行一个整数,表示最优行程安排下会死去的村民数量。

输入输出样例

输入 #1复制

6
40 200 1 300 2 10
输出 #1复制
1950
看一下代码:(代码还未交,如有问题欢迎回复)

#include<cstdio>
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int n=+;
ll a[n];
ll s[n];
ll f[n];//治愈前i个村庄并停到i的最少死亡的人数
//f数组转移时枚举断点,用w数组辅助转移
ll w[n][n];//从i出发治愈[i,j]中所有村庄再回到i的最少死亡人数
//在这里我们假设1-(i-1)已经治愈好了,i-n没有被救
//我们从w[i+1][j]转移w[i][j](区间dp),在计算时w[i-1][j]还没被计算
ll N; int main(){
scanf("%lld",&N);
for(int i=;i<=N;i++){
scanf("%lld",&a[i]);
s[i]=s[i-]+a[i];
}
for(int i=;i<=N;i++){
w[i][i]=s[N]-s[i];
}
//len是枚举的长度变量,这是一个dp方法,表示这次dp的区间长度,也可不用
for(int j=;j<=N;j++){
for(int i=j-;i;--i){
w[i][j]=w[i+][j]+min(*(s[N]-s[i])+s[N]-s[j],*a[i]*(j-i)+*(s[N]-s[j])+s[N]-s[i]);
//第一种策略:经过i时直接治疗,我们花费两天(治疗i一天,到达i+1一天),所以2*(s[n]-s[i]),我们要从i+1回到i,所以s[n]-s[j]
/*第二种策略:先越过去,回来的时候再治,所以有从i+1到i一天的代价,然后救i一天,所以2*(s[n]-s[j]),s[n]-s[i]已经计算了i到i+1
这一天代价,我们计算在这期间耽误多少天,就是j-i+j-i+j-i(过去,回来,救治),s[n]-s[i],这里是从i到j时,经过它的,为什么不乘2,
再回来的时候i+1已经治好了,肯定治好了,第二次经过一个电时,这个点一定已经治好了*/
}
}
memset(f,0x3f,sizeof(f));
f[]=;//边界dp(f)为0;
for(int i=;i<=N;i++){
for(int j=;j<i;j++){
f[i]=min(f[i],f[j]+(j!=)*(s[N]-s[j])+w[j+][i]+(i-j-)*s[N]-s[j]);//这里i,j不要看混了
//枚举断点,这里表示从i返回j+1,再回到i这是一次往返所以用w[j+1][i],表示j+1到i的时候并不是一次全治好
//因为最后数组停在了j+1,需要从j+1返回到i,所以i-(j+1)
//(j!=0)意思是j如果不是0,就为1,否则为0
}
}
printf("%lld\n",f[N]);
return ;
}

说明/提示

样例说明

我们用 C(k)C(k) 表示治愈 kk 号村庄,i \rightarrow ji→j 表示从村庄 ii 前进到村庄 jj,用逗号分隔每一天的行程安排,那么样例中的最优策略为:

1 \rightarrow 2 , C(2),2 \rightarrow 3 , 3 \rightarrow 4 , C(4) , 4 \rightarrow 3 , C(3) , 3 \rightarrow 2 , 2 \rightarrow 1 , C(1) , 1 \rightarrow 2 , 2 \rightarrow 3 , 3 \rightarrow 4 , 4 \rightarrow 5 , 5 \rightarrow 6 , C(6) , 6 \rightarrow 5 , C(5)1→2,C(2),2→3,3→4,C(4),4→3,C(3),3→2,2→1,C(1),1→2,2→3,3→4,4→5,5→6,C(6),6→5,C(5);

整个过程耗时 1818 天。


数据范围

对于 10\%10% 的数据,满足 N \le 10N≤10;

对于 30\%30% 的数据,满足 N \le 20N≤20;

对于 50\%50% 的数据,满足 N \le 60N≤60;

对于 100\%100% 的数据,满足 1 \le N \le 30001≤N≤3000,1 \le a_i \le 10^91≤ai​≤109。

P5774 [JSOI2016]病毒感染的更多相关文章

  1. JSOI2016 病毒感染(动态规划)

    题目传送门:洛谷P5774 思路来源:郭大佬(我就是凑不要脸的白嫖党 : P) 题目分析: 我们一点点来分析这道题: 起点固定为1号,所有村庄是按线性排列的,而不是图,所以我们应该用线性DP(废话 ) ...

  2. BZOJ4856 JSOI2016 病毒感染 区间DP

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

  3. [JSOI2016]病毒感染[dp]

    题意 有 \(n​\) 个村庄按标号排列,每个村庄有一个死亡速度 \(a_i​\) 表示每天死 \(a_i​\) 人(除非你治好这个村庄). 你从 1 号村庄出发,每天可以选择向相邻的村庄进发或者治愈 ...

  4. 区间dp提升复习

    区间\(dp\)提升复习 不得不说这波题真的不简单... 技巧总结: 1.有时候转移可以利用背包累和 2.如果遇到类似区间添加限制的题可以直接把限制扔在区间上,每次只考虑\([l,r]\)被\([i, ...

  5. 【LOJ】#2080. 「JSOI2016」病毒感染

    题解 那个限制表示一回头要治完前面的所有病人 我们处理一个g[i][j]表示治疗i到j的病人至少会死多少病人 \(g[i][j] = g[i + 1][j] + sum[i + 1,j] + min( ...

  6. BZOJ4856 病毒感染 [Jsoi2016] dp

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

  7. 全球性WannaCry蠕虫勒索病毒感染前后应对措施

    前言:针对WannaCrypt勒索病毒的讨论和技术文章是铺天盖地,大量的技术流派,安全厂家等纷纷献计献策,有安全厂家开发各种安全工具,对安全生态来说是一个好事,但对个人未必就是好事,我们国家很多用户是 ...

  8. loj#2071. 「JSOI2016」最佳团体

    题目链接 loj#2071. 「JSOI2016」最佳团体 题解 树形dp强行01分规 代码 #include<cstdio> #include<cstring> #inclu ...

  9. loj#2076. 「JSOI2016」炸弹攻击 模拟退火

    目录 题目链接 题解 代码 题目链接 loj#2076. 「JSOI2016」炸弹攻击 题解 模拟退火 退火时,由于答案比较小,但是温度比较高 所以在算exp时最好把相差的点数乘以一个常数让选取更差的 ...

随机推荐

  1. Java实现 LeetCode 598 范围求和 II(最小值相乘)

    598. 范围求和 II 给定一个初始元素全部为 0,大小为 m*n 的矩阵 M 以及在 M 上的一系列更新操作. 操作用二维数组表示,其中的每个操作用一个含有两个正整数 a 和 b 的数组表示,含义 ...

  2. Java实现 蓝桥杯VIP 算法训练 一元三次方程

    问题描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差 ...

  3. Java实现 LeetCode 210 课程表 II(二)

    210. 课程表 II 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0, ...

  4. Java实现 LeetCode 140 单词拆分 II(二)

    140. 单词拆分 II 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中.返回所有这些可能的句子. 说明: 分 ...

  5. 全面概述Gitee和GitHub生成/添加SSH公钥

    前言 现如今将代码开源已经成为软件开发行业的一种趋势,而现在比较有名的代码托管平台有GItHub.Gitee.Gitlab等相关平台.而我们在使用代码托管平台最为常见的就是如何将自己本地的代码推送到远 ...

  6. 用mvc框架查询数据库数据

    介绍下mvc框架,mvc框架一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑. 首先我们 ...

  7. zabbix 中文乱码

    环境 zabbix 3.4.7 centos 7.4 问题现象 zabbix 中文乱码     解决方法 1.先准备一个字体包    Windows路径 C:\Windows\Fonts\simkai ...

  8. KVM虚拟机使用NAT+iptables做端口映射

    环境介绍 有一个KVM宿主机,一个外网IP绑定在了宿主服务器上,但是希望直接用ssh访问上面的所有虚拟机,还想虚拟机提供外网服务, 解决方法如下: 环境为RHEL6.3,外网IP为 61.155.xx ...

  9. 使用vw进行移动端适配(nuxt项目)

    基于nuxt 2.0.0 一.安装postcss-px-to-viewport npm安装 npm install postcss-px-to-viewport --save-dev 或 yarn安装 ...

  10. Python + MySQL 批量查询百度收录

    做SEO的同学,经常会遇到几百或几千个站点,然后对于收录情况去做分析的情况 那么多余常用的一些工具在面对几千个站点需要去做收录分析的时候,那么就显得不是很合适. 在此特意分享给大家一个批量查询百度收录 ...