hdu 3669 Cross the Wall(给你n个矩形,长宽已知,求用不超过k个大矩形包含所有给定矩形,使得大矩形总面积和最小)

Cross the Wall

                                                            Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)
                                                                                           Total Submission(s): 4752    Accepted Submission(s): 894


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 w i and h i (1 <= w i, h i <= 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

题意:

给你n个矩形,长宽已知,求用不超过k个大矩形包含所有给定矩形,使得大矩形总面积和最小.

(1<=N<=50000,1<=K<=100,1 <= wi, hi <= 1000000)

 

思路:

首先按wi为主从大到小排序,hi为辅从大到小排序,如果后面的hi小于等于前面最大的hi,那么这个矩形肯定是可以被包含在前面已知的矩形中,换句话说,排好序之后的有用矩形一定是wi依次减小,hi依次增大

dp[k][i]表示到了第i,使用了k个矩形的面积的最小值,

显然dp[k][i]=min(dp[k-1][j]+a[i].h*a[j+1].w),这是一个显然的斜率dp

转化为坐标轴,x=-a[j+1].w,y=dp[k-1][j],维护一下斜率便能轻松的解决。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[101][50010];
int q[50010];
struct node{
    ll w,h;
}a[50010],b[50010];

ll getDP(int i,int j,int k){
    dp[j][i]=dp[j-1][k]+b[i].h*b[k+1].w;
}

ll getUP(int i,int j,int k){
    return dp[k][i]-dp[k][j];
}

ll getDOWN(int i,int j){
    return b[j+1].w-b[i+1].w;
}

bool cmp(node x,node y){
    if(x.w!=y.w)
        return x.w>y.w;
    return x.h>y.h;
}

int main(){
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF){
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&a[i].w,&a[i].h);
        int cnt=1;
        sort(a+1,a+n+1,cmp);
        b[cnt].w=a[1].w,b[cnt].h=a[1].h;
        ll maxv=a[1].h;
        for(int i=2;i<=n;i++){
            if(a[i].h<=maxv)
                continue;
            cnt++;
            b[cnt].w=a[i].w,b[cnt].h=a[i].h;
            maxv=a[i].h;
        }
        for(int i=1;i<=cnt;i++)
            dp[1][i]=b[1].w*b[i].h;
        int head,tail;
        for(int i=2;i<=k;i++){
            head=tail=0;
            q[tail++]=i-1;
            for(int j=i;j<=cnt;j++){
                while(head+1<tail&&getUP(q[head+1],q[head],i-1)<=b[j].h*getDOWN(q[head+1],q[head]))
                    head++;
                getDP(j,i,q[head]);
                while(head+1<tail&&getUP(j,q[tail-1],i-1)*getDOWN(q[tail-1],q[tail-2])<=getUP(q[tail-1],q[tail-2],i-1)*getDOWN(j,q[tail-1]))
                    tail--;
                q[tail++]=j;
            }
        }
        ll ans=100000000000000000LL;
        for(int i=1;i<=k;i++)
            ans=min(ans,dp[i][cnt]);
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值