前言

能够自己推出斜率优化的式子了...实属难得...

不过定义和实现都是参考了别人的博客的,╮(╯▽╰)╭...


woc...写博客的时候发现自己推的式子的变量有点问题.../难受

题目

All submissions for this problem are available.### Read problem statements in Hindi, Bengali, Mandarin Chinese, Russian, and Vietnamese as well.

Nikki has N

coconuts, she wants to prepare a special coconut soup for her best friend Mansi. In order to make this soup, she has to break Z

coconuts. For each coconut, there is a fixed number of times Nikki needs to hit it if she wants it to break. Nikki can only hit one coconut at the same time.

Their friend Sakshi is a troublemaker. This time, Sakshi shuffled the coconuts in some (unknown) way. You are given a sequence A1,A2,…,AN

with the following meaning: it is possible to label the coconuts 1 through N in such a way that for each valid i, the i-th coconut needs to be hit exactly Ai

times to break.

Nikki wants to prepare the soup as soon as possible, so she wants to minimise the number of times she has to hit coconuts in the worst case in order to break Z

coconuts. Formally, she wants to find a strategy of hitting coconuts, possibly depending on which coconuts broke after which hits, such that no matter which coconuts broke and when, it is guaranteed that after H hits, there will be Z broken coconuts, and there is no strategy with smaller H. Help Nikki find H

— the minimum required number of hits.

Input

  • The first line of the input contains a single integer Tdenoting the number of test cases. The description of T test cases follows.
  • The first line of each test case contains two space-separated integers N and Z .
  • The second line contains N space-separated integers A1,A2,…,AN .

Output

For each test case, print a single line containing one integer — the minimum required number of hits.

Constraints

  • 1≤T≤1,000
  • 1≤Z≤N≤10^3
  • 1≤Ai≤10^6 for each valid i
  • the sum of N⋅Z over all test cases does not exceed 3⋅10^6

Subtasks

Subtask #1 (10 points):

  • 1≤T≤100
  • 1≤N≤500
  • Z=1
  • 1≤Ai≤1,000 for each valid i
  • the sum of N⋅Z over all test cases does not exceed 3,000

Subtask #2 (90 points): original constraints

Example Input

2
2 1
50 55
2 1
40 100

Example Output

55
80

Explanation

Example case 1: Nikki can choose one coconut and try to hit it 55 times. It will break either after the 50-th hit or after the 55-th hit.

Example case 2: Nikki can choose one coconut and hit it 40 times. If it does not break, the other coconut must be the one that takes 40 hits to break, so she should hit the other coconut 40 times. In total, she needs to hit coconuts at most 80 times.

中文题意

题目描述
Nikki有N个椰子。她想给她最好的朋友Mansi炖椰子汤。炖椰子汤需要打开Z个椰子。
每个椰子壳有不同的坚硬度,需要不同的敲击次数才能打开。Nikki 每次只能敲一个椰子。
他们有一个朋友Sakshi 是个捣蛋鬼。这一次 Sakshi 悄悄地随机打乱了椰子的顺序。

已知打乱前椰子依次需要敲A1, A2,A3....An下才能打开。被Sakshi打乱后没人知道每个椰子所对应的打乱前的位置,但可以确定的是椰子还是同样的N个椰子,椰子被移动不会影响打开它所需的敲打次数。
Nkki想尽快炖好汤,所以她想知道在最坏的情况下她至少需要敲几下才能打开Z个椰子。也就是说,她需要设计一个敲打椰子的策略,使得无论椰子被打乱成什么顺序,都能保证一共敲击H以后必然有至少Z个椰子被打开。并且,不可能找到-一个策略能够让H的值更小。Nikki的策略可以依据某一次敲击是否打开了某个椰子的情况来做决策。
请帮Nikki找到这个最小的H值。.
输入格式
输入数据第一行包含一个整数T,表示数据组数。接下来是T组数据。
每组数据第一行包含两个整数 N和Z。
接下来的一行包含N个整数A1,A2,A3...An,意义见题目描述。
输出格式
对于每组数据,输出一行包含一个整数,表示最坏情况下至少需要敲多少下。

题目大意

有n个椰子,每个椰子有个“敲击次数”Ai,对于椰子 i 你要敲Ai次才能敲开此椰子

求敲开z个椰子所需要的最小敲击次数

分析

参考博客&特别鸣谢:Hit the Coconuts

假设现在有n个数,若想要保证能取出一个椰子,至少需要敲 n*min{A1,A2,A3...An}次

即至少需要敲 “(数的个数)*(这些数里的最小值)”那么多次
那么把这些数从大到小排序(这样当前敲的i号椰子就是前i个椰子中的最小值),则:

dp[ i ][ j ]:前 i 个里面保证能取出 j 个椰子需要敲的次数
dp[ i ][ k ] = min( dp[ j ][ k − 1 ] + ( i − j ) × a[ i ] )

可用斜率优化解决。这里的 a[ i ] 是单调递减的。即斜率是单调递减的。
那么下凸壳维护的最优决策点是越来越靠左的,所以pop的是右端,即是一个单调栈。


我自己的【斜率优化式子的推导】,好像变量名有点问题,与代码的变量名对不上...但是本蒟蒻不知道哪里出了问题..._(:зゝ∠)_...

(一)推导斜率式子

,其对应的dp值分别为:

若 j 的DP值比 l 的更优(更小),则:

移项化简得:

若满足上式,则 l 可以踢出队了(因为j更优嘛)


(二)再考虑如何维护并取得DP值(也就是答案)

刚刚上面说了, a[ i ] 是单调递减的,即斜率是单调递减的
那么下凸壳维护的最优决策点是越来越靠左的,所以pop的是右端

为什么呢?我可能太弱了,一开始没看懂,后来豁然开朗2333...这里我将整个过程想详细讲一讲:

首先,要从去掉“不够优秀”的点,及检查tail与tail-1的斜率是否满足>=a[ i ]

再解决新点的加入,从右往左来看,下凸壳的形状仍是上凸的(由不凹到凹)

而从左往右来看,有的点会与i形成下凹(由凹到不凹),所以要从队尾开始检查,删去不合法的点

例如下图,tail不合法,出队,然后又检查tail-1,以此类推

而在下图中,tail合法

所以(一)维护了下凸壳后,取对尾元素更新DP值,(二)再删去加入i后会不合法的点,最后将i入队,解决!

暴力DP代码

//刚刚那个版本居然暴力都没打对qwq...
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1000,INF=0x3f3f3f3f;
ll a[MAXN+5],dp[MAXN+5][MAXN+5];
//dp[i][j]:前i个椰子敲j个所需的最小花费
int n,z;
bool cmp(int a,int b)
{return a>b;
}
void Solve()
{sort(a+1,a+n+1,cmp);memset(dp,0x3f,sizeof(dp));for(int i=0;i<=n;i++)dp[i][1]=i*a[i];for(int i=1;i<=n;i++)for(int k=1;k<=i;k++)for(int j=1;j<i;j++)dp[i][k]=min(dp[i][k],dp[j][k-1]+(i-j)*a[i]);ll ans=INF;for(int i=z;i<=n;i++)ans=min(ans,dp[i][z]);printf("%lld\n",ans);
}
int main()
{int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&z);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);Solve();}return 0;
}

优化DP代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1000,INF=0x3f3f3f3f;
const double eps=1e-10;
ll a[MAXN+5],que[MAXN+5],dp[MAXN+5][MAXN+5];
//dp[i][j]:前i个椰子敲j个所需的最小花费
int n,z;
bool cmp(int a,int b)
{return a>b;
}
ll Y(int i,int cur)
{return dp[i][cur];
}
ll K(int i,int j,int cur)
{return (Y(i,cur)-Y(j,cur))/(i-j);
}
void Solve()
{sort(a+1,a+n+1,cmp);for(int i=0;i<=n;i++)dp[i][1]=i*a[i];for(int k=2;k<=z;k++)//式子中的"k-1"是相同的,则看成一个常数,循环做z次即可 {int head=0,tail=0;que[++head]=0;que[++tail]=k-1;for(int i=k;i<=n;i++){while(head<tail&&K(que[tail],que[tail-1],k-1)>=a[i])tail--;int j=que[tail];dp[i][k]=dp[j][k-1]+(i-j)*a[i];while(head<tail&&K(que[tail],que[tail-1],k-1)>=K(que[tail],i,k-1))tail--;que[++tail]=i;}}ll ans=INF;for(int i=z;i<=n;i++)ans=min(ans,dp[i][z]);printf("%lld\n",ans);
}
int main()
{int t;scanf("%d",&t);while(t--){scanf("%d%d",&n,&z);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);Solve();}return 0;
}

【斜率优化】Codechef July Challenge 2019——Hit the Coconuts相关推荐

  1. Codechef July Challenge 2018 : Subway Ride

    传送门 首先(想了很久之后)注意到一个性质:同一条边有多种颜色的话保留3种就可以了,这是因为假如最优解要求当前位置与相邻两条边都不相同,那么只要有3条边,就肯定可以满足这一点. 完事就做一个nlogn ...

  2. HDU3507 Print Article —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3507 Print Article Time Limit: 9000/3000 MS (Java/Others)    Mem ...

  3. The LeVoice Far-field Speech Recognition System for VOiCES from a Distance Challenge 2019

    The LeVoice Far-field Speech Recognition System for VOiCES from a Distance Challenge 2019 Yulong Lia ...

  4. 斜率优化之凸包优化与李超线段树

    文章目录 前言 凸包优化 第一步 第二步 最后一步 例一 转移方程 凸包优化 代码 例二 题目大意 转移方程 凸包优化 代码 李超线段树 思想 插入 查询 代码 例三 代码 例四 转移方程 怎么做 代 ...

  5. 斜率优化DP 总结(含凸优化)

    我看了很多%d%a%l%a%o的博客,使我对其印象深刻. 确实,斜率优化的DP式一般都是: f[i]=minf[j]+a[i]∗a[j]+...f[i]=min{f[j]+a[i]*a[j]}+... ...

  6. 斜率优化DP小结(含凸优化)

    目录 斜率DP 2019.8.4 update 凸优化 斜率DP 我看了很多%d%a%l%a%o的博客,使我对其印象深刻. 确实,斜率优化的DP式一般都是: \[f[i]=min(f[j]+a[i]* ...

  7. BZOJ1597: [Usaco2008 Mar]土地购买(dp 斜率优化)

    题意 题目链接 Sol 重新看了一遍斜率优化,感觉又有了一些新的认识. 首先把土地按照\((w, h)\)排序,用单调栈处理出每个位置第向左第一个比他大的位置,显然这中间的元素是没用的 设\(f[i] ...

  8. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )

    既然每块都要买, 那么一块土地被另一块包含就可以不考虑. 先按长排序, 去掉不考虑的土地, 剩下的土地长x递增, 宽y递减 dp(v) = min{ dp(p)+xv*yp+1 } 假设dp(v)由i ...

  9. 【BZOJ3963】[WF2011]MachineWorks cdq分治+斜率优化

    [BZOJ3963][WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先 ...

最新文章

  1. 对学习JAVA的总结 第一次课
  2. 数字签名与HTTPS详解
  3. 中国数字故障记录仪行业市场供需与战略研究报告
  4. 在TensorFlow中实现文本分类的卷积神经网络
  5. 排序算法-桶排序(入门级别)
  6. 朗逸机器人_几张动图告诉你,工业机器人无所不能!
  7. authorware学习
  8. mysql模糊匹配关键字_MySQL 关键字模糊匹配,并按照匹配度排序
  9. 什么是视频封装格式和编码格式
  10. 【云和恩墨大讲堂】视频课程震撼来袭-SQL优化精选案例
  11. 【数字设计与计算机体系结构】2021-09-26-数字设计与计算机体系结构课程(四)
  12. SSL_WRITE在断网时的表现
  13. 优秀的产品,离不开这4个 层面
  14. 【poj 2488】A Knight's Journey 中文题意题解代码(C++)
  15. 请编写一个正方体类,类的私有数据成员是边长,要求用公有成员函数实现以下功能:1. 由键盘分别输入正方体的边长2. 计算并输出正方体的体积
  16. BZOJ1016 || 洛谷P4208 [JSOI2008]最小生成树计数【矩阵树定理】
  17. pytorch 批量归一化BatchNorm1d和BatchNorm2d的用法、BN层参数 running_mean running_var变量计算 验证
  18. PHP 多任务秒级定时器的实现方法
  19. Python strip()方法
  20. 【001】基于51单片机的DS18B20温度检测与报警装置的proteus仿真设计

热门文章

  1. 《数学之美》读书笔记(2)
  2. notepad++精美主题字体
  3. monolog php,Monolog:PHP 日志记录工具
  4. 半导体器件基础09:MOS管特性和应用(1)
  5. 李宏毅_Machine Learning_1
  6. python 实现栈和队列
  7. c# winform 打印机控制帮助类
  8. 旗袍女装网站分类优化:频道页优化
  9. 入门Python爬虫开发-欧阳桫-专题视频课程
  10. uni-app如何跨页面传参