hdu 3669(斜率优化DP)
Cross the Wall
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 327680/327680 K (Java/Others)
Total Submission(s): 4479 Accepted Submission(s): 812
The Great Wall is a huge wall with infinite width and height, so the only way to cross is to dig holes in it. All people in Rectland can be considered as rectangles with varying width and height, and they can only dig rectangle holes in the wall. A person can pass through a hole, if and only if the person’s width and height is no more than the hole’s width and height both. To dig a hole with width W and height H, the people should pay W * H dollars. Please note that it is only permitted to dig at most K holes for security consideration, and different holes cannot overlap each other in the Great Wall. Remember when they pass through the wall, they must have their feet landed on the ground.
Given all the persons’ width and height, you are requested to find out the minimum cost for digging holes to make all the persons pass through the wall.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 50100
#define LL long long
#define inf 0x3f3f3f3f3f3f3f3f3f3f
using namespace std;
LL dp[maxn][];
int que[maxn];
int n,k;
int head,tail;
struct node
{
LL w;
LL h;
};
node p[maxn];
bool cmp(node a,node b)
{
if(a.w==b.w)
return a.h<b.h;
else
return a.w>b.w;
}
LL getdp(int i,int j,int k)
{
//return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
return dp[k][j-]+p[k+].w*p[i].h;
} LL getup(int j,int k1,int k2) //yj-yk部分 k1>k2
{
//return dp[j]+sum[j]*sum[j]-(dp[k]+sum[k]*sum[k]);
return dp[k1][j-]-dp[k2][j-];
}
LL getdown(int j,int k1,int k2)
{
//return 2*(sum[j]-sum[k]);
return p[k2+].w-p[k1+].w;
} void solve()
{
head=;
tail=;
que[tail++]=;
dp[][]=;
for(int i=;i<=n;i++)
{
dp[i][]=inf;
dp[][i]=;
}
for(int j=;j<=k;j++)
{
head=tail=;
que[tail++]=;
for(int i=;i<=n;i++)
{
//从头开始找当前状态的最优决策,g[que[head+1],que[head]] < sum[i],说明que[head+1]比que[head]更优,删除que[head]
while(head+ < tail && getup(j,que[head+],que[head]) <= getdown(j,que[head+],que[head]) * p[i].h )
head++; //注意写成相乘,不然要考虑除数是否为负数
dp[i][j]=getdp(i,j,que[head]); //从尾往前,加入当前状态,如果g[i,que[tail]] < g[que[tail],que[tail-1]] ,可以排除que[tail]
while(head+<tail && getup(j,i,que[tail-])*getdown(j,que[tail-],que[tail-])<=getup(j,que[tail-],que[tail-])*getdown(j,i,que[tail-]))
tail--;
que[tail++]=i;
}
} /*for(int j=1;j<=k;j++)
{
for(int i=1;i<=n;i++)
printf("%lld ",dp[i][j]);
printf("\n");
}*/
printf("%lld\n",dp[n][k]); }
int main()
{
while(~scanf("%d%d",&n,&k))
{
//init();
for(int i=;i<=n;i++)
scanf("%lld%lld",&p[i].w,&p[i].h);
sort(p+,p+n+,cmp); int j=;
for(int i=;i<=n;i++)
{
if(p[i].h<p[j].h)
continue;
else
{
p[++j]=p[i];
}
}
n=j;
//for(int i=1;i<=n;i++)
// printf("%lld %lld\n",p[i].w,p[i].h);
solve();
}
return ;
}
四边形优化:
目前位置接触到两种形式的方程可以采用四边形优化:
1
a d[i][j]=min(d[i-1][k]+p[k+1].w*p[i].h)
写成这种形式,而不是上面那种,是因为四边形优化的s[i][j]的递推顺序好写
b s[i-1][j]<s[i][j]<s[i][j+1];
观察a和b式,i从小到大,j从大到小.然后初始化第一行和第n+1列,进行递推。
2 (类似于石子合并)
d[i][j]=d[i][k]+d[k+1][j]+w[i][j]
s[i][j-1]<s[i][j]<s[i+1][j]
这时候的递推顺序,是通过先枚举长度,再枚举起点,然后就可以现在要算的状态之前都算过了。
(超时代码,目前只能写到这了)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 50100
#define LL long long
#define inf 0x3f3f3f3f3f3f3f3f3f3f
using namespace std;
LL d[maxn][];
int w[maxn][];
int n,k;
struct node
{
LL w;
LL h;
};
node p[maxn];
bool cmp(node a,node b)
{
if(a.w==b.w)
return a.h<b.h;
else
return a.w>b.w;
}
void solve()
{
for(int i=;i<=n;i++)
{
d[][i]=p[].w*p[i].h;
w[][i]=; } for(int i=;i<=k;i++)
{
w[i][n+]=n;
for(int j=n;j>=i;j--)
{
d[i][j]=inf;
for(int s=w[i-][j];s<=w[i][j+];s++)
{
if(d[i][j]>(d[i-][s]+p[s+].w*p[j].h) )
{
d[i][j]=(d[i-][s]+p[s+].w*p[j].h);
w[i][j]=s;
}
}
}
}
/*for(int i=0;i<=k;i++)
{
for(int j=0;j<=n+1;j++)
printf("%d ",w[i][j]);
printf("\n");
}
printf("\n");
for(int i=0;i<=k;i++)
{
for(int j=0;j<=n;j++)
printf("%lld ",d[i][j]);
printf("\n");
}*/
printf("%lld\n",d[k][n]); }
int main()
{
while(~scanf("%d%d",&n,&k))
{
//init();
memset(d,,sizeof(d));
for(int i=;i<=n;i++)
scanf("%lld%lld",&p[i].w,&p[i].h);
sort(p+,p+n+,cmp); int j=;
for(int i=;i<=n;i++)
{
if(p[i].h<p[j].h)
continue;
else
{
p[++j]=p[i];
}
}
n=j; solve();
}
return ;
}
hdu 3669(斜率优化DP)的更多相关文章
- HDU 4258 斜率优化dp
Covered Walkway Time Limit: 30000/10000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU 2829 斜率优化DP Lawrence
题意:n个数之间放m个障碍,分隔成m+1段.对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小. 设: d(i, j)表示前i个数之间放j个炸弹能得到的最小值 sum(i)为前缀和,co ...
- hdu 3045 斜率优化DP
思路:dp[i]=dp[j]+sum[i]-sum[j]-(i-j)*num[j+1]; 然后就是比较斜率. 注意的时这里j+t<=i: #include<iostream> #in ...
- Print Article HDU - 3507 -斜率优化DP
思路 : 1,用一个单调队列来维护解集. 2,假设队列中从头到尾已经有元素a b c.那么当d要入队的时候,我们维护队列的下凸性质, 即如果g[d,c]<g[c,b],那么就将c点删除.直到找到 ...
- HDU 3507 斜率优化dp
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3507斜率优化dp
Print Article Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)To ...
- HDU 3507 斜率优化 DP Print Article
在kuangbin巨巨博客上学的. #include <iostream> #include <cstdio> #include <cstring> #includ ...
- HDU 2993 MAX Average Problem(斜率优化DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...
- hdu 2829 Lawrence(斜率优化DP)
题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...
随机推荐
- BZOJ1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害
n<=3000个点m<=20000条无向边的图,有p<=n个出发点,每个出发点都不可拆,现拆一些点使每个出发点都不能到达点1,求最小点数. 简单的最小割.每个点拆成两个x和y,无向边 ...
- xhprof安装&&使用[转载]
编译安装 wget http://pecl.php.net/get/xhprof-0.9.2.tgz tar zxf xhprof-0.9.2.tgz cd xhprof-0.9.2/extensio ...
- codeforces 873F(后缀数组)
题意 给一个长度不超过200000的字符串s,假定有一个字符串a,这个字符串在s中出现次数是f(a),你需要让$|a|f(a)$最大. 但是有一些位置是禁止的,即以该位置为结束位置的字符串不计数. 分 ...
- hdu6196 happpy happy happy (meet in middle + 剪枝)
题意 从1到n共计n(<=90)个物品,每个物品有一个价值a[i],儿子和爸爸轮流做游戏,儿子先手.儿子每次选价值最大的{最左边,最右边}的物品,如果价值一样大, 则选取最左边的物品. 爸爸每次 ...
- Spring Cloud(9):Config配置中心
Config配置中心作用简单来讲:统一配置,方便管理 开源配置中心: 1.百度Disconf 2.阿里Diamand 3.Spring Cloud Config 搭建Config-Server 快速上 ...
- sql 2005 安装
http://blog.csdn.net/wochuailimin/article/details/6120462 http://www.cnblogs.com/huangcong/archive/2 ...
- 聊聊高并发(四十)解析java.util.concurrent各个组件(十六) ThreadPoolExecutor源代码分析
ThreadPoolExecutor是Executor运行框架最重要的一个实现类.提供了线程池管理和任务管理是两个最主要的能力.这篇通过分析ThreadPoolExecutor的源代码来看看怎样设计和 ...
- Android中AsyncTask使用具体解释
在Android中我们能够通过Thread+Handler实现多线程通信.一种经典的使用场景是:在新线程中进行耗时操作.当任务完毕后通过Handler向主线程发送Message.这样主线程的Handl ...
- C#如何引用定义好的dll文件
1 添加引用,找到dll文件 2 引用类的名称空间,生成类的实例,调用类的方法,测试OK.
- 【PostgreSQL】PostgreSQL操作-psql基本命令
在阅读的过程中有不论什么问题,欢迎一起交流 邮箱:1494713801@qq.com QQ:1494713801 一.建立数据库连接 ---------------- 接入PostgreSQL数 ...