题目大意:

  有几座山,如果一座山左右两边的山比它矮,那么可以在这个山上建房子,你有一台挖掘机,每天可以挖一座山一米,问你需要花多少代价可以分别盖1、2、3……座房子。(给出山的数量,以及每座山的高度)。

题目分析:

  性质1:不会有两座相邻的山都建房子。性质 2:一座山盖房子就不会被挖,被挖就不会盖房子(两条废话)

  每一座山有两种情况:建房子或者不建,可以用一维来保存([ 0 ]/[ 1 ])。

  1到第 i 座山的代价和只与 i 前面的两座山有关:如果这座山( i )不建,那么他前面那座山( i-1 )可建可不建,它的代价就是前面山代价的最小值。如果这座山(i)建房,那么它前面的那座山(i - 1)一定不建,它的代价就与前两座山有关系。以此类推,就可以遍历全部求最值。

  我们定义一个数组dp[ i ] [ j ] [0/1 ]用来表示前 i 座山中建了 j 个房子的代价 ,最后一维表示当前第 i 座山是否建房子。

  如果这座山选择不盖房子,那么它的代价取决于前一座山的情况。

  

  如图:

  

dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]+cost(i-1,i));//如果前一座山盖房子,那么这座山有可能挖

cost(i,j)函数表示 i 盖房子需要挖 j 挖多少代价。

int cost(int i,int j){
if(a[j]>=a[i]){
return a[j]-a[i]+1;
}else{
return 0;
}
}

如果这座山盖房子:

如图,这座山的代价与前面两座山都有关。

如果 i 选择盖房子,那么 i - 1 肯定盖不了,而 i - 2盖不盖房子会产生影响。

如果 i - 2 不盖房子,那就没什么可以担心的,直接挖 i - 1 到比 i 矮就可以了。

如果 i - 2 盖房子,那就要比较到底把 i - 1 挖到比谁矮。

dp[i][j][1]=min(dp[i-2][j-1][0]+cost(i,i-1),dp[i-2][j-1][1]+max(cost(i,i-1),cost(i-2,i-1)));

最后要输出的结果,是盖 1,2,3,……栋房子的最小代价。

首先我们需要知道最多盖几栋房子:

  设想:一共n座山,相邻山不能同时盖房子,所以要么盖1、3、5、7……要么盖2、4、6、8……

  最多盖( n + 1 )/2栋房子(自己推一下,记住整形运算自动向下取整)

这样结果就出来了,输出相应的 min(dp[ i ][ j ][ 0 ],dp[ i ][ j ][ 1 ])即可。

全代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5010;
int dp[maxn][maxn][2],a[maxn];
int cost(int i,int j){
if(a[j]>=a[i]){
return a[j]-a[i]+1;
}else{
return 0;
}
}
int n,cnt;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
a[i]=0;
for(int j=1;j<=n;j++){
dp[i][j][0]=dp[i][j][1]=0x3fffffff;
}
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
dp[1][1][1]=0;
dp[2][1][1]=cost(2,1);
dp[2][1][0]=cost(1,2);
for(int i=3;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]+cost(i-1,i));
dp[i][j][1]=min(dp[i-2][j-1][0]+cost(i,i-1),dp[i-2][j-1][1]+max(cost(i,i-1),cost(i-2,i-1))); if(2*j>=i)break;
}
}
int cnt=(n+1)/2;
for(int j=1;j<=cnt;j++){
printf("%d ",min(dp[n][j][1],dp[n][j][0]));
}
printf("\n"); }

最新文章

  1. CLR垃圾回收的设计
  2. Configuration
  3. spring源码学习之【准备】jdk动态代理例子
  4. 【Zend Studio】10.6.0版本设置默认编码为UTF-8
  5. Power of Four
  6. JS原型与原型链终极详解(转)
  7. python 处理cookie简单很多啊 httpclient版本是4.3.3
  8. Selenium WebDriver + Grid2 + RSpec之旅(三) ----入门小例子
  9. wlan0 Interface doesn&#39;t support scanning : Device or resource busy
  10. html 格式的email 编辑
  11. Codeforces 450 C. Jzzhu and Chocolate
  12. 568. Maximum Vacation Days
  13. 关于php内存释放问题 内存溢出问题(二)
  14. Android 开发笔记___SD卡基本操作__图片读取写入
  15. linux中syscall调用号查看
  16. C标准中关于空指针的那些事
  17. vba读文本如果文本文件太大会提示错误!
  18. windows编程按小时生成日志文件
  19. bzoj1036点权模板题
  20. windows无法安装到这个磁盘。选中的磁盘采用GPT分区形式 Windows 检测到 EFI 系统分区格式化为 NTFS。将 EFI 系统分区个数化为 FAT32,然后重新启动安装

热门文章

  1. (.net core环境下)图形验证,人机交互,一个不够我给你两个
  2. C、算法、操作系统杂记《malloc 0大小是什么行为》
  3. 透过 Cucumber 学习 BDD
  4. Linux实战(16):Centos history命令进阶
  5. 我还在生产玩 JDK7,JDK 15 却要来了!
  6. 使用vue-cli(vue脚手架)快速搭建项目-2
  7. html 背景花瓣特效--1
  8. c++ 动态库的加载
  9. P4568 [JLOI2011]飞行路线 / P2939 [USACO09FEB]Revamping Trails G
  10. PHP添加新扩展包的步骤