【BZOJ4856】【JSOI2016】病毒感染

11人阅读 评论(0) 收藏 举报
分类:

【题目链接】

【思路要点】

  • 由于起始点是1号节点,如果在某个时刻,我们向左走了一个单位,那么我们就必须将左侧的村庄全部治愈。
  • 因此,如果我们能计算出\(last_{i,j}\)表示从村庄\(i\)出发,治愈\([i,j]\)内所有村庄并走到村庄\(j+1\)所付出的最小代价(注意这里的代价应当计算\([j+1,N]\)内的村庄在该过程中的死亡)那么就可以用一个简单的DP解决本题。
  • 现在问题在于如何计算出\(last_{i,j}\)。
  • 考虑枚举\(j\),这样\([j+1,N]\)内的村庄村民死亡的速度就确定了。
  • 令\(suf_i\)表示\([i,N]\)内村庄的权值和。
  • 若已知\(last_{i+1,j}\),\(last_{i,j}\)可能有两种转移方式:
  • 1、在村庄\(i\)处先治愈村庄\(i\),总代价为\(2 * suf_{i + 1} + last_{i + 1,j}\)。
  • 2、在治愈\([i+1,j]\)内所有村庄后治愈村庄\(i\),总代价为\(first_{i,j} + suf_{j + 1} * (j - i + 1)\)。
  • 其中\(first_{i,j}\)表示从村庄\(i\)出发,治愈\([i,j]\)内所有村庄并走到村庄\(i\)所付出的最小代价。
  • \(first_{i,j}\)可以用类似的转移求出,在此不再赘述。
  • 时间复杂度\(O(N^2)\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3005;
const long long INF = 4e18;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
int n;
long long dp[MAXN], suf[MAXN], val[MAXN];
long long first[MAXN][MAXN], last[MAXN][MAXN];
int main() {
	read(n);
	for (int i = 1; i <= n; i++)
		read(val[i]);
	for (int i = n; i >= 1; i--)
		suf[i] = suf[i + 1] + val[i];
	for (int i = n; i >= 1; i--) {
		first[i][i] = suf[i + 1];
		last[i][i] = 2 * suf[i + 1];
		for (int j = i - 1; j >= 1; j--) {
			first[j][i] = min(2 * suf[j + 1] + first[j + 1][i] + suf[i + 1], suf[j + 1] + first[j + 1][i] + 2 * suf[i + 1] + val[j] * (i - j) * 3);
			last[j][i] = min(2 * suf[j + 1] + last[j + 1][i], first[j][i] + suf[i + 1] * (i - j + 1));
		}
	}
	for (int i = n; i >= 1; i--) {
		dp[i] = INF;
		for (int j = i; j <= n; j++)
			chkmin(dp[i], dp[j + 1] + last[i][j]);
	}
	writeln(dp[1]);
	return 0;
}

查看评论

4038: 医疗援助/4856: [Jsoi2016]病毒感染

题目链接题目大意:医疗团队来到n个村庄,n个村庄依次标号为1,2,…n。第i个村庄有ai个感染者。从1出发,每天可以去相邻村庄/治愈所在村庄,如果第i个村庄没有被治疗,那么每天这个村庄会死去ai个人,...
  • Mmh2000
  • Mmh2000
  • 2017年08月21日 19:15
  • 206

JSOI2016一轮Day1

JSOI2016
  • Birdman_JC_Xiao
  • Birdman_JC_Xiao
  • 2016年04月15日 19:36
  • 599

【HDU】4856 Tunnels BFS+状压DP

Tunnels Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...
  • u013368721
  • u013368721
  • 2014年07月08日 21:04
  • 723

BZOJ4850: [Jsoi2016]灯塔

BZOJ4850很容易发现sqrt(|i−j|)sqrt(|i-j|)很多情况下都是相等的。 那么就可以考虑分块。(题目应该是hj≤hi+p−sqrt(|i−j|)hj≤hi+p-sqrt(|i-j...
  • Ep1C_HeReT1c
  • Ep1C_HeReT1c
  • 2017年06月06日 18:22
  • 323

[JSOI2016]无界单词

题目大意一个只由a和b组成的长度为n的字符串,如果kmp后next[n]=0,则称之为无界单词。给定n和m,求长度为n的无界单词个数以及第m小的。第一问正难则反! 设f[i]表示长度为i的无界单词数...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2016年04月25日 19:05
  • 773

[bzoj4755][JSOI2016]扭动的回文串

题目大意给定两个长度为n的字符串A和B。 扭动的回文串定义为a[i..j]与b[j..k]相接成的字符串为回文串或者a、b的一个回文子串。随便搞搞对a、b分别做一次manacher。 然后我们只需...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2016年05月23日 21:26
  • 1189

【JSOI2016】最佳团队

DescriptionInputOutputSample Input1 2 1000 1 0 1 1000 1Sample Output0.001Data Constraint分析这种最大化形如∑...
  • WorldWide_D
  • WorldWide_D
  • 2016年06月02日 12:49
  • 585

JZOJ4513. 【JSOI2016】独特的树叶

题目大意 给两棵树,分别有n和n+1个节点。已知其中一棵树比另一棵多一个叶子节点。求编号最小的可能多出来的节点编号。 Data Constraint 1≤N≤10^5...
  • Akak__ii
  • Akak__ii
  • 2016年06月03日 22:47
  • 616

[JZOJ4465][JSOI2016?]飞机调度

题目大意有nn个城市,两两飞行时间为ti,jt_{i,j}(ti,jt_{i,j}不一定等于tj,it_{j,i},保证ti,i=0t_{i,i}=0)。 mm条商务航线,要求在时刻DiD_i从城市...
  • a_crazy_czy
  • a_crazy_czy
  • 2016年04月24日 13:04
  • 911

[JZOJ4512][JSOI2016]最佳团队

题目大意一棵树,有n+1n+1个节点,根编号为00。 每个非根节点都有两个权值sis_i和pip_i,父亲rir_i。 要求选择K+1K+1个节点,最大化 ∑pi∑si \sum p_i\ove...
  • a_crazy_czy
  • a_crazy_czy
  • 2016年06月26日 11:12
  • 736
    个人资料
    持之以恒
    等级:
    访问量: 9748
    积分: 2683
    排名: 1万+
    文章分类
    文章存档