问题分析

首先,如果一个人的\(w\)和\(h\)均小于另一个人,那么这个人显然可以被省略。如果我们将剩下的人按\(w[i]\)递增排序,那么\(h[i]\)就是递减。

之后我们考虑DP。

我们设\(f[i][j]\)为到第\(i\)个人,打了\(j\)个洞的花费。于是我们可以得到如下DP过程:

for( LL i = 1; i <= N; ++i ) F[ i ][ 1 ] = w[ i ] * h[ 1 ];
for( LL j = 2; j <= K; ++j )
for( LL i = j; i <= N; ++i ) {
f[ i ][ j ] = INF;
for( LL k = j - 1; k < i; ++k )
F[ i ][ j ] = min( F[ i ][ j ], F[ k ][ j - 1 ] + w[ i ] * h[ k + 1 ] );
}
Ans = F[ N ][ K ];

我们将第二维滚动掉,节省空间:

for( LL i = 1; i <= N; ++i ) F1[ i ] = w[ i ] * h[ 1 ];
for( LL j = 2; j <= K; ++j ) {
for( LL i = j; i <= N; ++i ) {
F2[ i ] = INF;
for( LL k = j - 1; k < i; ++k )
F2[ i ] = min( F2[ i ], F1[ k ] + w[ i ] * h[ k + 1 ] );
}
memcpy( F1, F2, sizeof( F2 ) );
}
Ans = F1[ N ][ K ];

再考虑优化最里面一层循环:

设\(l>k\)且从\(l\)转移优于从\(k\)转移,那么就有

\[F1[l]+w[i]*h[l+1]<F1[k]+w[i]*h[k+1]
\]

化简,得

\[\frac{F_1[l]-F_1[k]}{h[k+1]-h[l+1]}<w[i]
\]

然后就可以斜率优化了。具体的斜率优化讲解可以看这里。

参考程序

#include <bits/stdc++.h>
#define LL long long
using namespace std; const LL INF = 1e18 + 10;
const LL MaxN = 50010, MaxK = 110;
LL N, K;
struct CitizenAttribute {
LL Width, Hight;
CitizenAttribute( LL Width_ = 0, LL Hight_ = 0 ) {
Width = Width_; Hight = Hight_; return;
}
bool operator < ( const CitizenAttribute Other ) const {
return Width < Other.Width || Width == Other.Width && Hight > Other.Hight;
}
};
CitizenAttribute Citizens[ MaxN ];
bool IsSkiped[ MaxN ];
LL L, R, Queue[ MaxN ], F1[ MaxN ], F2[ MaxN ];
LL NumAfterSkip; inline void Clear() {
memset( Citizens, 0, sizeof( Citizens ) );
memset( IsSkiped, false, sizeof( IsSkiped ) );
memset( F1, 0, sizeof( F1 ) );
return;
} inline void SkipContainedCitizen() {
CitizenAttribute Last = CitizenAttribute( 0, 0 );
for( LL i = N; i >= 1; --i )
if( Citizens[ i ].Hight <= Last.Hight ) IsSkiped[ i ] = true;
else Last = Citizens[ i ];
NumAfterSkip = 0;
for( LL i = 1; i <= N; ++i )
if( !IsSkiped[ i ] )
Citizens[ ++NumAfterSkip ] = Citizens[ i ];
return;
} inline bool Less( LL i, LL j, LL Limit ) {
LL DeltaY = F1[ j ] - F1[ i ];
LL DeltaX = Citizens[ i + 1 ].Hight - Citizens[ j + 1 ].Hight;
return DeltaY <= Limit * DeltaX;
} inline bool Greater( LL i, LL j, LL k ) {
LL DeltaY1 = F1[ j ] - F1[ i ];
LL DeltaY2 = F1[ k ] - F1[ j ];
LL DeltaX1 = Citizens[ i + 1 ].Hight - Citizens[ j + 1 ].Hight;
LL DeltaX2 = Citizens[ j + 1 ].Hight - Citizens[ k + 1 ].Hight;
return DeltaY1 * DeltaX2 >= DeltaY2 * DeltaX1;
} void Work() {
LL Ans = INF;
Clear();
for( LL i = 1; i <= N; ++i )
scanf( "%lld%lld", &Citizens[ i ].Width, &Citizens[ i ].Hight );
sort( Citizens + 1, Citizens + N + 1 );
SkipContainedCitizen();
for( LL i = 1; i <= NumAfterSkip; ++i ) F1[ i ] = Citizens[ i ].Width * Citizens[ 1 ].Hight;
Ans = min( Ans, F1[ NumAfterSkip ] );
for( LL j = 2; j <= K && j <= NumAfterSkip; ++j ) {
memset( F2, 0, sizeof( F2 ) );
L = R = 0; memset( Queue, 0, sizeof( Queue ) );
Queue[ R++ ] = j - 1;
for( LL i = j; i <= NumAfterSkip; ++i ) {
while( L + 1 < R && Less( Queue[ L ], Queue[ L + 1 ], Citizens[ i ].Width ) )
++L;
F2[ i ] = F1[ Queue[ L ] ] + Citizens[ Queue[ L ] + 1 ].Hight * Citizens[ i ].Width;
while( L + 1 < R && Greater( Queue[ R - 2 ], Queue[ R - 1 ], i ) )
--R;
Queue[ R++ ] = i;
}
memcpy( F1, F2, sizeof( F2 ) );
Ans = min( Ans, F1[ NumAfterSkip ] );
}
printf( "%lld\n", Ans );
return;
} int main() {
while( scanf( "%lld%lld", &N, &K ) == 2 )
Work();
return 0;
}

HDU 3669 [Cross the Wall] DP斜率优化的更多相关文章

  1. HDU 3669 Cross the Wall(斜率DP+预处理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669 题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得 ...

  2. hdu 3669 Cross the Wall(斜率优化DP)

    题目连接:hdu 3669 Cross the Wall 题意: 现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能 ...

  3. 动态规划DP的斜率优化 个人浅解 附HDU 3669 Cross the Wall

    首先要感谢叉姐的指导Orz 这一类问题的DP方程都有如下形式 dp[i] = w(i) + max/min(a(i)*b(j) + c(j)) ( 0 <= j < i ) 其中,b, c ...

  4. HDU 3669 Cross the Wall

    题目大意 给定 \(N\) 个矩形的宽和高, \((h_1, w_1), (h_2, w_2), \dots, (h_n w_n)\) . 现需要确定 \(k\) (\(k \le K\), \(K\ ...

  5. HDU 3507 Print Article(DP+斜率优化)

     Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) ...

  6. HDU 2993 MAX Average Problem dp斜率优化

    MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  7. HDU 3507 [Print Article]DP斜率优化

    题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...

  8. 【BZOJ-4518】征途 DP + 斜率优化

    4518: [Sdoi2016]征途 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 230  Solved: 156[Submit][Status][ ...

  9. 【BZOJ-3437】小P的牧场 DP + 斜率优化

    3437: 小P的牧场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 705  Solved: 404[Submit][Status][Discuss ...

随机推荐

  1. golang(2):基本数据类型和操作符

    1). 文件名 & 关键字 & 标识符 . 所有go源码都以 .go 结尾 . 标识符以字母或下划线开头,大小写敏感 . _ 是特殊标识符,用来忽略结果 . 保留关键字 golang  ...

  2. O020、理解 Glance

    参考https://www.cnblogs.com/CloudMan6/p/5384923.html   OpenStack 由 Glance 提供 Image 服务.   理解 Glance    ...

  3. js css3 固定点拖拽旋转

    一.直接上效果图: 然后是代码: 一共两种实现方式: <!DOCTYPE html> <html lang="en"> <head> <m ...

  4. Express multer 文件上传

    npm multer 文件上传 Express app 范本就不写了,仅记录一下上传部分的代码. const fs = require('fs'); const express = require(' ...

  5. 请写出正则表达式(regex),取得下列黄色部分的字符串 TEL: 02-236-9655/9659 FAX:02-236-9654 (黄色部分即02-236-9655/9659 ) ( 测试面试题)

    请写出正则表达式(regex),取得下列黄色部分的字符串 TEL: 02-236-9655/9659 FAX:02-236-9654 答: package test1; import java.uti ...

  6. 忘记oracle的sys用户密码如何修改以及Oracle 11g 默认用户名和密码

    忘记除SYS.SYSTEM用户之外的用户的登录密码 CONN SYS/PASS_WORD AS SYSDBA; --用SYS (或SYSTEM)用户登录 ALTER USER user_name ID ...

  7. ffmpeg3.3.2命令行参数笔记

    组成: 1.libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含demuxers和muxer库: 2.libavcodec:用 ...

  8. Delphi 参数的传递

  9. deep_learning_Function_tf.identity()

    这两天看batch normalization的代码时,学到滑动平均窗口函数ExponentialMovingAverage时,碰到一个函数tf.identity()函数,特此记录. tf.ident ...

  10. PyCharm上unittest 测试用例两种执行方式

    每次讲到unittest测试框架的时候,经常有同学在群里反映,为啥我的运行不是按照我往suite里添加的用例顺序执行的,为什么别人的能跑出来报告,我的就不行... 当然,首先确认代码是OK的,如果代码 ...