问题分析

首先,如果一个人的\(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. AssertionError [ERR_ASSERTION]: Task function must be specified,gulp版本不一致

    报错信息: vue项目打包报错 > innovate-admin-vue@ build /home/soldier/SOLDIER/IDE_project/webStorm_project/in ...

  2. # 「NOIP2010」关押罪犯(二分图染色+二分答案)

    「NOIP2010」关押罪犯(二分图染色+二分答案) 洛谷 P1525 描述:n个罪犯(1-N),两个罪犯之间的仇恨值为c,m对仇恨值,求怎么分配使得两件监狱的最大仇恨值最小. 思路:使最大xxx最小 ...

  3. Git_基础命令

    gitinit//初始化一个Git仓库" role="presentation">gitinit//初始化一个Git仓库gitinit//初始化一个Git仓库 gi ...

  4. 小白学习tornado框架第一站-环境设置

    首先建立一个虚拟环境 mkvirtualenv -p /usr/bin/python3 tornado_1 安装tornado框架 pip install tornado  pycham中建立同步 创 ...

  5. leetcode中等题

    # Title Solution Acceptance Difficulty Frequency     1 Two Sum       44.5% Easy     2 Add Two Number ...

  6. 学习笔记--APIO 2018 二分专题 By wuvin

    前言: 在APIO 2018 Day2下午听wuvin讲二分,听了一上午的神仙,现在终于有可以听懂了. 专题: 平均边权最大 题目链接:https://www.questoj.cn/problem/3 ...

  7. 移动端H5开发自适应技巧

    移动端H5开发,必要要做到自适应各种分辨率的手机,下面由我为大家大致说一下,需要3步走 第一:head标签中添加: <meta name="viewport" content ...

  8. 部署Dashboard,监控应用

    部署web UI(dashboard)用于监控node资源 参见文档:https://blog.csdn.net/networken/article/details/85607593 官网:https ...

  9. 帝国cms 常用标签汇总

    1.列表内容标签 [!--empirenews.listtemp--]<!--list.var1-->[!--empirenews.listtemp--] 2.分页标签 [!--show. ...

  10. Nginx默认配置语法

    Nginx默认配置语法 1. 我们进入  /etc/nginx/目录下,打开  nginx.conf文件 2. 我们来解析下 这里面标签和各模块的作用 # 设置nginx服务的系统使用用户 user ...