codeJan喜欢观察世界。有一天,codeJan发现一个非常奇怪的现象。有一些年轻的青蛙聚集在一条直线上的某些位置上,同一个位置可能有多个青蛙。这些青蛙每次只会向前跳一米,并且每只青蛙每跳一次都会发出’WA’的一声。codeJan想在一些青蛙的位置上放置黑洞来收集全部的青蛙。在黑洞位置上的青蛙会直接掉进黑洞中不会发出任何叫声,其余的青蛙经过若干次跳跃都会掉进在它前面的最近的黑洞。因为WA类似WrongAnswer,所以codeJan想要知道他合理地安排黑洞的位置,最少可以听到多少声WA?在听到最少声WA时,需要准备的每个黑洞的容量至少为多少?黑洞的容量体现为可以容纳的青蛙的最大数量,所有黑洞的容量应该都相同。

输入描述:

第一行一个正整数T≤20表示测试组数。每组测试样例的第一行是两个正整数n,m,分别表示存在青蛙的位置和可以放置黑洞的数量。接下来n行,每行包含两个正整数a[i],b[i]分别表示第i组青蛙的位置(单位:米)和这个位置上青蛙的数量。

输出描述:

对于每组测试用例用一行输出两个正整数分别表示最少可以听到多少声WA和黑洞的最少容量。用空格隔开,行末无空格。
示例1

输入

2
3 1
1 1
2 2
3 3
3 2
1 1
4 2
2 3

输出

8 6
3 4

说明

对于第一个样例,只能放在 1 位置,因此听到的 WA 的次数为:1*0+2*1+3*2=8,所有青蛙汇聚在一次,容量至少为 6。
对于第二个样例,可以放在 1 和 4 位置,因此听到的 WA 的次数为:1*0+3*1+2*0=3,1 位置和 2 位置的青蛙汇聚在一 起,需要容量为 4;4 位置的青蛙单独在一起,需要容量为 2。因此容量至少为 4

备注:

输入保证a[i] ≠a[j](i ≠j),1≤m≤n≤100,1≤a[i],b[i]≤106。

题解

$dp$,二分。

$dp[i][j]$表示到$i$位置,分了$j$段的最小花费,每一个区间的花费可以预处理。

$dp[1][m]$就是第一个答案。

对于第二个答案,容量越大,最小花费肯定越小,容量越小,最小花费越大,利用这个单调性就可以二分,假设二分到的容量为$x$,那么$dp$的时候外加一个条件控制一下区间和要小于等于$x$。

#include <bits/stdc++.h>
using namespace std; const int maxn = 100 + 10;
int T, n, m;
struct X {
int a, b;
}s[maxn];
long long cost[maxn][maxn];
long long dp[maxn][maxn];
long long sum[maxn][maxn];
long long limit; bool cmp(const X& a, const X& b) {
return a.a < b.a;
} int check(long long mid) {
for(int i = 1; i <= n; i ++) {
dp[i][1] = 1e18;
if(sum[i][n] <= mid) dp[i][1] = cost[i][n];
}
for(int j = 2; j <= m; j ++) {
for(int i = n - j + 1; i >= 1; i --) {
dp[i][j] = 1e18;
for(int k = i + 1; k <= n; k ++) {
if(dp[k][j - 1] != 1e18 && sum[i][k - 1] <= mid) {
dp[i][j] = min(dp[i][j], dp[k][j - 1] + cost[i][k - 1]);
}
}
}
}
if(limit == dp[1][m]) return 1;
return 0;
} int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) {
scanf("%d%d", &s[i].a, &s[i].b);
}
sort(s + 1, s + 1 + n, cmp);
for(int i = 1; i <= n; i ++) {
for(int j = i; j <= n; j ++) {
cost[i][j] = cost[i][j - 1] + 1LL * (s[j].a - s[i].a) * s[j].b;
sum[i][j] = sum[i][j - 1] + s[j].b;
}
}
for(int i = 1; i <= n; i ++) dp[i][1] = cost[i][n];
for(int j = 2; j <= m; j ++) {
for(int i = n - j + 1; i >= 1; i --) {
dp[i][j] = 1e18;
for(int k = i + 1; k <= n; k ++) {
dp[i][j] = min(dp[i][j], dp[k][j - 1] + cost[i][k - 1]);
}
}
}
limit = dp[1][m];
long long ans2 = sum[1][n];
long long L = 1, R = ans2;
while(L <= R) {
long long mid = (L + R) / 2;
if(check(mid)) ans2 = mid, R = mid - 1;
else L = mid + 1;
}
printf("%lld %lld\n", limit, ans2);
}
return 0;
}

Wannafly挑战赛7 D - codeJan与青蛙的更多相关文章

  1. Wannafly挑战赛7 B - codeJan与旅行

    题目描述 codeJan 非常喜欢旅行.现在有 n 个城市排在一条线上,并且 codeJan 的位置不和任何一个城市的位置重叠.codeJan 想要游览 m 个城市,同时因为时间是不断变化的,游览一个 ...

  2. Wannafly挑战赛25游记

    Wannafly挑战赛25游记 A - 因子 题目大意: 令\(x=n!(n\le10^{12})\),给定一大于\(1\)的正整数\(p(p\le10000)\)求一个\(k\)使得\(p^k|x\ ...

  3. Wannafly挑战赛27

    Wannafly挑战赛27 我打的第一场$Wannafly$是第25场,$T2$竟然出了一个几何题?而且还把我好不容易升上绿的$Rating$又降回了蓝名...之后再不敢打$Wannafly$了. 由 ...

  4. Wannafly 挑战赛 19 参考题解

    这一次的 Wannafly 挑战赛题目是我出的,除了第一题,剩余的题目好像对大部分算法竞赛者来说好像都不是特别友好,但是个人感觉题目质量还是过得去的,下面是题目链接以及题解. [题目链接] Wanna ...

  5. Wannafly挑战赛21A

    题目链接 Wannafly挑战赛21A 题解 代码 #include <cstdio> #include <cmath> #define MAX 1000005 #define ...

  6. Wannafly挑战赛24游记

    Wannafly挑战赛24游记 A - 石子游戏 题目大意: A和B两人玩游戏,总共有\(n(n\le10^4)\)堆石子,轮流进行一些操作,不能进行下去的人则输掉这局游戏.操作包含以下两种: 把石子 ...

  7. Wannafly挑战赛25C 期望操作数

    Wannafly挑战赛25C 期望操作数 简单题啦 \(f[i]=\frac{\sum_{j<=i}f[j]}{i}+1\) \(f[i]=\frac{f[i]}{i}+\frac{\sum_{ ...

  8. Wannafly挑战赛18B 随机数

    Wannafly挑战赛18B 随机数 设\(f_i\)表示生成\(i\)个数有奇数个1的概率. 那么显而易见的递推式:\(f_i=p(1-f_{i-1})+(1-p)f_{i-1}=(1-2p)f_{ ...

  9. Wannafly挑战赛22游记

    Wannafly挑战赛22游记 幸运的人都是相似的,不幸的人各有各的不幸. --题记 A-计数器 题目大意: 有一个计数器,计数器的初始值为\(0\),每次操作你可以把计数器的值加上\(a_1,a_2 ...

随机推荐

  1. 第5章-Vue.js交互及生命周期练习

    一.学习目标 使用网络请求进行前后端交互 (重点) 理解钩子函数的作用  (难点) 掌握Vue.js过滤器的使用方法 了解Vue.js事件的深入用法  (重点) 二.仿写留言板 2.1.实现" ...

  2. 在使用Hibernate save()方法的时候 报错: org.hibernate.exception.ConstraintViolationException:could not perform addBath

    org.hibernate.exception.ConstraintViolationException:could not perform addBath 错误可能原因:实体属性的值与数据库字段类型 ...

  3. HDU 1573 CRT

    CRT模板题 /** @Date : 2017-09-15 13:52:21 * @FileName: HDU 1573 CRT EXGCD.cpp * @Platform: Windows * @A ...

  4. 【leetcode 简单】第一题 两数之和

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...

  5. Oracle笔记之序列(Sequence)

    Oracle中序列是一种数据对象,可以视为一个等差数列,我们自增就是一个遍历这个数列的过程,可以取当前值,也可以将当前值自加n后返回,Sequence与表没有太大的关系,有的时候如果表的主键是数值类型 ...

  6. JS设计模式——4.继承(概念)

    类式继承 0.构造函数 一个简单的Person类 function Person(name){ this.name = name; } Person.prototype.getName = funct ...

  7. fileIO和OS操作文件和目录

    1.FileIO操作文件 # 文件IO,读取文件和创建文件 # 1.读取键盘输入 x=input("please input number") print("您输入的是& ...

  8. CounterBreach安装测试的全部过程

    CounterBreach安装测试的全部过程 1安装数据库审计的网关 Admin进入 Impcfg初始化 选择网关 是否替换另一个网关? 否 是否改变默认管理口 设置管理口地址 192.168.1.2 ...

  9. Vuex-Action

    Action 类似于 mutation,不同在于: Action 提交的是 mutation,而不是直接变更状态. Action 可以包含任意异步操作. 让我们来注册一个简单的 action: con ...

  10. MAC和PHY的区别

    一块以太网网卡包括OSI(开方系统互联)模型的两个层.物理层和数据链路层.物理层定义了数据传送与接收所需要的电与光信号.线路状态.时钟基准.数据编码和电路等,并向数据链路层设备提供标准接口.数据链路层 ...