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

Problem Description
“Across the Great Wall, we can reach every corner in the world!” Now the citizens of Rectland want to cross the Great Wall. 
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.
 
Input
There are several test cases. The first line of each case contains two numbers, N (1 <= N <= 50000) and K (1 <= K <= 100), indicating the number of people and the maximum holes allowed to dig. Then N lines followed, each contains two integers wi and hi (1 <= wi, hi <= 1000000), indicating the width and height of each person.
 
Output
Output one line for each test case, indicates the minimum cost.

 
Sample Input
2 1 1 100 100 1 2 2 1 100 100 1
 
Sample Output
10000 200
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  3662 3661 3664 3665 3666 
题目描述:
给你n个人,每个人的宽度和高度已知,最多可以修k个门,修门的花费为门的面积,求最少花费。
d[i][j]=min(d[k][j-1]+p[k+1].w*p[i].h);时间复杂度为5*10^12,可以采用斜率优化或者四边形优化。
采取斜率优化:
设k1>k2,k1优于k2,dp[k1][j-1]+p[k1+1].w*p[i].h<=dp[k2][j-1]+p[k2+1].w*p[i].h;
化简得:dp[k1][j-1]-dp[k2][j-1]<p[i].h*(p[k2+1].w-p[k1+1].w)
预处理d[i][0]=inf,d[0][i]=0;
还需注意i和j的枚举顺序,先枚举j,再枚举i,每次枚举j的时候都需要重新初始化i的解集
#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)的更多相关文章

  1. HDU 4258 斜率优化dp

    Covered Walkway Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  2. HDU 2829 斜率优化DP Lawrence

    题意:n个数之间放m个障碍,分隔成m+1段.对于每段两两数相乘再求和,然后把这m+1个值加起来,让这个值最小. 设: d(i, j)表示前i个数之间放j个炸弹能得到的最小值 sum(i)为前缀和,co ...

  3. hdu 3045 斜率优化DP

    思路:dp[i]=dp[j]+sum[i]-sum[j]-(i-j)*num[j+1]; 然后就是比较斜率. 注意的时这里j+t<=i: #include<iostream> #in ...

  4. Print Article HDU - 3507 -斜率优化DP

    思路 : 1,用一个单调队列来维护解集. 2,假设队列中从头到尾已经有元素a b c.那么当d要入队的时候,我们维护队列的下凸性质, 即如果g[d,c]<g[c,b],那么就将c点删除.直到找到 ...

  5. HDU 3507 斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  6. HDU 3507斜率优化dp

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  7. HDU 3507 斜率优化 DP Print Article

    在kuangbin巨巨博客上学的. #include <iostream> #include <cstdio> #include <cstring> #includ ...

  8. HDU 2993 MAX Average Problem(斜率优化DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给定一个长度为n(最长为10^5)的正整数序列,求出连续的最短为k的子序列平均值的最大 ...

  9. hdu 2829 Lawrence(斜率优化DP)

    题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...

随机推荐

  1. 【dp】E. Selling Souvenirs

    http://codeforces.com/contest/808/problem/E 题意:给定n个重量为可能1,2,3的纪念品和各自的价值,问在背包总重量不超过m的条件下总价值最大为多少. 其中1 ...

  2. poj 1163 数塔

    #include<stdio.h> #include<string.h> #define N 110 int dp[N][N]; int a[N][N]; int Max(in ...

  3. vue2.0 类淘宝不同屏幕适配及px与rem转换问题

    因为项目需要,vue开发项目,必须将已写的以px为单位的部分,转换为rem.要是全部转换,这大量的计算量,哪怕是sublime Text 的cssrem插件,也是一个庞大的工作量.所以,直接使用插件没 ...

  4. 怎样检查Android网络连接状态

    在发送任何HTTP请求前最好检查下网络连接状态,这样可以避免异常.这个教程将会介绍怎样在你的应用中检测网络连接状态. 创建新的项目 1.在Eclipse IDE中创建一个新的项目并把填入必须的信息.  ...

  5. maven 编译出错 Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean

    eclipse在使用maven的tomcat控件编译java程序时,报错 Failed to execute goal org.apache.maven.plugins:maven-clean-plu ...

  6. poj 2480 Longge's problem [ 欧拉函数 ]

    传送门 Longge's problem Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7327   Accepted: 2 ...

  7. 出现 Assigning the return value of new by reference is deprecated in xxxx &&“Warning: Call-time pass-by-reference has been deprecated”怎么办?

    自从php5.3,越来越多的人会遇到“Assigning the return value of new by reference is deprecated in xxxx”这样的提示,尤其是在国外 ...

  8. Populating Next Right Pointers in Each Node (DFS,没想到)

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  9. 转 linux socket的select函数例子

    使用select函数可以以非阻塞的方式和多个socket通信.程序只是演示select函数的使用,功能非常简单,即使某个连接关闭以后也不会修改当前连接数,连接数达到最大值后会终止程序. 1. 程序使用 ...

  10. jenkins修改日志级别方法

    1.jenkins日志有时候也会消耗掉很大内存,在传输时也会消耗掉大量带宽,如图,300+M的日志大小,太夸张了吧 2.修改日志级别的方法: 在配置文件里修改,重启后永久生效,配置路径:/etc/sy ...