问题分析

首先,如果一个人的\(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. 【2017.12.02】C组比赛总结

    这次考得不怎么样,只有200分! T1:读书 这题水水水! 这题就是一道循环题嘛! 直接一边循环一边做就好了! T2:恐怖分子 这题我是直接暴力的. 这题就是求至少用多少条经过(x0,y0)的不同直线 ...

  2. Python 入门 之 包

    Python 入门 之 包 1.包 (1)什么是包? 文件夹下具有_ init.py _的文件夹就是一个包 (2)包的作用: 管理模块(文件化) (3)包的导入: 导入: 启动文件要和包文件是同级 绝 ...

  3. 在web项目中配置log4j

    在web.xml中添加如下代码 <context-param> <param-name>contextConfigLocation</param-name> < ...

  4. JDK8~13新特性概览

    JDK8 1. 接口default 与 static 关键字 /** * jdk8中接口可以使用声明default和static修饰的方法 * static修饰的方法和普通的方法一样,可以被直接调用 ...

  5. .Net高并发解决思路

    转自: 本文如有不对之处,欢迎各位拍砖扶正.另源码在文章最下面,大家下载过后先还原一下nuget包,需要改一下redis的配置,rabbitmq的配置以及Ef的连接字符串.另外使用的是CodeFirs ...

  6. Mysql学习(一)之简单介绍

    数据库简介 数据库分类 关系型数据库:MySQL.Oracle.SQLServer.Access.db2.fox pro 文件型数据库:sqlite.mongodb 空间型数据库: 数据库分为两端 数 ...

  7. ACM的一点基础知识

    所摘内容来自于XJTU小学期ACM培训PPT log 默认以2为底 计算机一秒可以看作1e8次 保证数据计算精度及数据所需必要大小 a=1LL*a*a%p//在计算时通过乘以1LL,临时将Int转化为 ...

  8. 常见Http访问错误小结

    4xx 客户端错误# 400 bad request 错误的请求 # 401 未携带身份信息 # 403 forbidden 权限不够 # 404 Not Found# 405 请求方式不允许 5xx ...

  9. js之运算符(位运算符)

    一.概念 位运算在数字底层(表示数字的32个数位)进行运算的.由于位运算是低级的运算操作,所以速度往往也是最快的,但是它很不直观,许多场合不能够使用.大多数语言都提供了按位运算符,恰当的使用按位运算符 ...

  10. 一个密码经过多次MD5加密能否提高安全性?Java MD5盐值加解密

    什么是MD5? MD5(Message Digest Algorithm 5,信息摘要算法5),是计算机广泛使用的摘要算法(又称哈希算法)之一.MD5是将一段信息,通过其不可逆的字符串变换算法,产生了 ...