一道不难的DP题,主要是为了总结这类最优化题的思路;同时还学到了一个新操作

传送门:$>here<$

题意

给出一个长度为$N$的序列,要求最多使用s个数字进行量化(有损压缩),即代替原数字:使得量化后各个被代替的数与代替的数的差的平方之和最小。

数据范围:$n \leq 100, s \leq 10$

Solution

动态规划的常规思路

容易发现肯定选择数值相近的一些数字用一个数字取替代,所以肯定先排序。

排序完后就是一个简单的dp题了。$dp[i][j]$表示前$i$个数字,使用$j$个数字量化的最小误差。当前决策一定关于第$i$个数字有关,问题在于究竟这一段要多长。在枚举一个k,转移就很明显了:

$dp[i][j]=Min\{dp[k][j-1]+quantize(k+1,i)\}$

究竟用什么来做量化的值

问题转化为了如何求$quantize$函数。就这道题的范围来看,从最小到最大枚举也是没有问题的。但实际上有$O(1)$方法。

设我们选择$m$来量化,也就是说函数$y=\sum\limits_{i=l}^{r}(m-a[i])^2$最小。问题转化为求此函数的最小值。

这是个二次函数,所以展开后直接求导(或直接使用顶点公式),找到顶点的$x$坐标即可。

$y=\sum\limits_{i=l}^{r}(m-a[i])^2=(r-l+1)m^2-2m\sum\limits_{i=l}^{r}a[i]+\sum\limits_{i=l}^{r}a[i]^2$

当$y'=2(r-l+1)m-2\sum\limits_{i=l}^{r}a[i]=0$时

$m=\frac{\sum\limits_{i=l}^{r}a[i]}{r-l+1}$

这就是平均值!由此我们得到结论:当利用平均值来当量化值时,差的平方之和最小。

透过题解看本质

其实对于这类最优化dp问题,可以看做是递归问题。dp的本质是记忆化搜索,只不过可以利用递推来实现。当我搜到这一步时需要枚举来决策当前需要多长的一段来量化,而剩余的则不需要递归,而是直接利用之前做好的最优子结构。这就是dp为什么比dfs快了。其实dp就是暴力,它终究需要考虑所有需要且可能的情况。

my code

具体在实现的时候通过统计前缀和以及平方的前缀和来$O(1)$完成求解。注意把$m$代入求误差时也要利用前缀和。

注意平均值应该四舍五入。

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = ; int w = ; register char c = getchar();
for(; c ^ '-' && (c < '' || c > ''); c = getchar());
if(c == '-') w = -, c = getchar();
for(; c >= '' && c <= ''; c = getchar()) x = (x<<) + (x<<) + c - ''; return x * w;
}
int T,N,s;
int a[MAXN],dp[MAXN][],sum[MAXN],ssqr[MAXN];
inline int calc(int l, int r, int m){
int res = ;
res += m*m * (r-l+);
res += ssqr[r] - ssqr[l-];
res -= *m*(sum[r]-sum[l-]);
return res;
}
inline int quantize(int l, int r){
int m = (sum[r]-sum[l-]) / (r-l+);
return Min(calc(l,r,m), calc(l,r,m+));
}
inline int Solve(){
sort(a+,a+N+);
sum[] = ssqr[] = ;
for(int i = ; i <= N; ++i){
sum[i] = sum[i-] + a[i];
ssqr[i] = ssqr[i-] + a[i] * a[i];
}
memset(dp,INF,sizeof(dp));
for(int i = ; i <= s; ++i) dp[][i] = ;
for(int i = ; i <= N; ++i){
for(int j = ; j <= s; ++j){
for(int k = ; k < i; ++k){
dp[i][j] = Min(dp[i][j], dp[k][j-] + quantize(k+,i));
}
}
}
return dp[N][s];
}
int main(){
// freopen(".in","r",stdin);
T = read();
while(T--){
N = read(), s = read();
for(int i = ; i <= N; ++i){
a[i] = read();
}
printf("%d\n", Solve());
}
return ;
}

「Algospot」量化QUANTIZE的更多相关文章

  1. 「Algospot」津巴布韦ZIMBABWE

    同时考验对状压DP和数位DP的理解: 传送门:$>here<$ 题意 给出一个数字$e$,现在对$e$通过$m$进行变换得到$x$:变换的要求是:1.只能改变原数字$e$各个数位的顺序(可 ...

  2. 「Algospot」龙曲线DRAGON

    一道考验思维的好题,顺便总结求第k大问题的常规思路: 传送门:$>here<$ 题意 给出初始串FX,每分形一次所有X替换为X+YF,所有Y替换为FX-Y.问$n$代字符串第$p$位起长度 ...

  3. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  4. 面试都在问的「微服务」「RPC」「服务治理」「下一代微服务」一文带你彻底搞懂!

    ❝ 文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) ❞ 单体式应用程序 与微服务相对的另一个概念是传统的「单体式应用程 ...

  5. 《Offer一箩筐》一份高质量「简历」撰写指南,望打扰!!

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」. 如果觉得 「不错」 的朋友,欢迎 「关注 + 留言 + 分享」,文末有完整的获取链接,您的支持是我前进的最大的动力! Hi~ 这里是 ...

  6. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  7. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  8. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  9. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

随机推荐

  1. vue-resource实现数据的绑定、添加、删除

    vue-resource实现数据的绑定.添加.删除 <!DOCTYPE html> <html lang="en"> <head> <ti ...

  2. .NET Core和.NET Standard有什么不同

        近日,微软发布了.NET Core 2.0,但是开发人员中间仍然存在一些疑惑,就是.NET Core..NET Standard.Xamarin和.NET Framework有什么不同. .N ...

  3. 基础知识:IDE集成开发环境(pycharm)、基本数据类型、用户的交互、运算符

    今日内容: 1.IDE集成开发环境(pycharm) 2.基本数据类型(int.float.str.list.dict) 3.用户的交互(注释.输入input.输出print) 4.运算符(分类及使用 ...

  4. DRDS分布式SQL引擎—执行计划介绍

    摘要: 本文着重介绍 DRDS 执行计划中各个操作符的含义,以便用户通过查询计划了解 SQL 执行流程,从而有针对性的调优 SQL. DRDS分布式SQL引擎 — 执行计划介绍 前言 数据库系统中,执 ...

  5. tomcat,httpd 日志格式说明

    tomcat 日志说明 配置文件server.xml 默认日志格式为 pattern="%h %l %u %t "%r" %s %b" 推荐使用 pattern ...

  6. Source-Based XSS Test Cases

    Single Reflection Case 01 - Direct URL Injection (no parameter) payload: https://brutelogic.com.br/x ...

  7. Python 基于pykafka简单实现KAFKA消费者

    基于pykafka简单实现KAFKA消费者   By: 授客 QQ:1033553122         1.测试环境 python 3.4 zookeeper-3.4.13.tar.gz 下载地址1 ...

  8. 简单易懂的单元测试框架-gtest(二)

    简介     事件机制用于在案例运行前后添加一些操作(相当于挂钩函数).目前,gtest提供了三种等级的事件,分别: 全局级,所有案例执行的前后 TestSuite级,某一个案例集的前后 TestCa ...

  9. ChromeDriver截图

    一.NuGet安装Selenium.Chrome.WebDriver和Selenium.WebDriver 二.将packages\Selenium.Chrome.WebDriver.2.45\dri ...

  10. SAM failed to write changes to the database 问题处理

    问题: Windows Storage Server 2012 R2 发布NAS服务,客户创建用户和组时报错,事件查看器系统日志下报错Event ID 12288,内容如下: SAM failed t ...