HDU 3669 [Cross the Wall] DP斜率优化
问题分析
首先,如果一个人的\(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\)转移,那么就有
\]
化简,得
\]
然后就可以斜率优化了。具体的斜率优化讲解可以看这里。
参考程序
#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斜率优化的更多相关文章
- HDU 3669 Cross the Wall(斜率DP+预处理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3669 题目大意:有n(n<=50000)个矩形,每个矩形都有高和宽,你可以在墙上最多挖k个洞使得 ...
- hdu 3669 Cross the Wall(斜率优化DP)
题目连接:hdu 3669 Cross the Wall 题意: 现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能 ...
- 动态规划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 ...
- HDU 3669 Cross the Wall
题目大意 给定 \(N\) 个矩形的宽和高, \((h_1, w_1), (h_2, w_2), \dots, (h_n w_n)\) . 现需要确定 \(k\) (\(k \le K\), \(K\ ...
- HDU 3507 Print Article(DP+斜率优化)
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
- HDU 2993 MAX Average Problem dp斜率优化
MAX Average Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- 【BZOJ-4518】征途 DP + 斜率优化
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 230 Solved: 156[Submit][Status][ ...
- 【BZOJ-3437】小P的牧场 DP + 斜率优化
3437: 小P的牧场 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 705 Solved: 404[Submit][Status][Discuss ...
随机推荐
- CF39H 【Multiplication Table】
这题可以枚举出每个i,j 位置的数>需要用到进制转换 int zh(int x){ long long sum=0,i=0; while(x){ sum=sum+((x%n)*pow(10,i) ...
- spark教程(10)-sparkSQL
sparkSQL 的由来 我们知道最初的计算框架叫 mapreduce,他的缺点是计算速度慢,还有一个就是代码比较麻烦,所以有了 hive: hive 是把类 sql 的语句转换成 mapreduce ...
- Codeforces 1229C. Konrad and Company Evaluation
传送门 首先考虑如何算出答案,考虑枚举中间那个点,显然每个点作为中间的点的次数为入度乘出度 所以答案就是每个点的入度乘出度之和 然后每个点开一个 $vector$ 维护从它出去的点数,每次修改的时候直 ...
- Codeforces 1221F. Choose a Square
传送门 对于某个点 $(x,y)$ ,不妨设 $x<y$ 因为如果 $x>y$ 直接按 $y=x$ 对称一下即可 当且仅当正方形左下角 $(a,a)$ 满足 $a<=x$,右上角 $ ...
- 使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题
在使用parquet-hadoop.jar包解析parquet文件时,遇到decimal类型的数据为乱码,具体解决方法如下: 使用parquet-Hadoop.jar解析httpfs服务提供的parq ...
- qt webengineview 加载本地资源方式
一.如果把资源添加到本地资源qrc库里了,请使用 ui->preview->setUrl(QUrl("qrc:/HelloWorld2.html")): 二.如果没有现 ...
- react + antd Form表单校验
非空限制 {getFieldDecorator('name', { rules: [{ required: true, message: '名称不能为空', }],})( <Input plac ...
- 一个密码经过多次MD5加密能否提高安全性?Java MD5盐值加解密
什么是MD5? MD5(Message Digest Algorithm 5,信息摘要算法5),是计算机广泛使用的摘要算法(又称哈希算法)之一.MD5是将一段信息,通过其不可逆的字符串变换算法,产生了 ...
- 使用redislive监控redis
redis监控工具redislive的安装 1. pip安装 如果主机没有pip先安装pip工具 wget --no-check-certificate https://github.com/pypa ...
- 织梦DedeCMS栏目列表常见序号的调用标签
我们在制作dedecms模板时,源代码中的[field:global name=autoindex/]标签很好用可以调用数字序号,此标签最简单的用法就是按内容条数来获取数字序号,但有的时候发现使用该标 ...