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;
}

最新文章

  1. web前端代码编写体验
  2. python用Tesseract读取图片中的中文,出现乱码
  3. Python第二模块(文件和函数)
  4. 不支持C++11 decltype的噩耗
  5. Oracle to_char()函数的使用细则
  6. 淘宝(阿里百川)手机客户端开发日记第一篇 android 主框架搭建(一)
  7. 解决Linux下Tomcat日志目录下的catalina.log日志文件过大的问题
  8. 绕过杀毒软件抓取windows密码
  9. 遇见了这个问题:App.config提示错误“配置系统未能初始化”
  10. 我开发了一个产品--Markdown Notes
  11. 【iOS开发-21】UINavigationController导航控制器初始化,导航控制器栈的push和pop跳转理解
  12. Fluent Nhibernate code frist简单配置
  13. Python——正则表达式特殊符号及用法
  14. TypeError: &#39;encoding&#39; is an invalid keyword argument for this function
  15. 1945 : 卡贩子Carol
  16. Python系列:五、异常处理-技术流ken
  17. C/S和B/S应用程序的区别
  18. JACKSON详解
  19. 如何用C#动态编译、执行代码
  20. python 给字符串加颜色

热门文章

  1. Tensorflow BatchNormalization详解:3_使用tf.layers高级函数来构建带有BatchNormalization的神经网络
  2. Asp.Net MVC 自定义登录过滤器
  3. poj 1067 取石子游戏 (威佐夫博弈)
  4. HDU 2138 Miller-Rabin 模板题
  5. AlloyTouch 简介
  6. spring bean初始化及销毁你必须要掌握的回调方法
  7. JavaScript中innerText和innerHTML的区别
  8. 无key值的json数组解析
  9. VueJS ElementUI el-table 的 formatter 和 scope template 不能同时存在
  10. struts获得参数(属性,对象,模型驱动)