【BZOJ1859】【ZJOI2006】碗的叠放

题目大意:给你n个碗,求如何堆叠,使得它们的总高度最低。

首先,我们枚举碗的叠放顺序。

假设我们已经堆好了前i个碗,那么在堆第i+1个碗时,我们要将第i+1个碗与前i个碗比较,确定第i+1个碗的离地高度。

对于第i个碗和第j个碗的比较,我们分五种情况讨论(以下画图只画半个碗):

上方的碗底比下方的碗顶大,直接放上去即可

 

 上方的碗底比下方碗底小,直接放上去即可
 

 

 上方的碗边缘斜率小于下方的碗,且上方的碗比下方的碗大,的计算出其中一个碗的斜率,然后卡位即可
 

 

 情况和上图类似,也是直接卡位即可。
 

 

 上方的碗边缘斜率大于下方的碗,也是直接卡位。

具体的细节可以看我的代码。

然后请一定要仔细检查所有细节(我错了一个字母调了2h)

 1 #include<bits/stdc++.h>
 2 #define M 10
 3 using namespace std;
 4  
 5 struct node{
 6     double a,b,c,d;
 7     node(){a=b=c=d=0;}
 8     node(double aa,double bb,double cc,double dd){
 9         a=aa; b=bb; c=cc; d=dd;
10     }
11     double xl(){return (d-b)/(c-a);}
12     friend double operator -(node a,node b){
13         double p=a.b; a.b-=p; a.d-=p;
14         //if(a.a>=b.a&&a.c>=b.c) return p;
15         if(a.c<=b.a) return p+a.d;
16         if(a.xl()>b.xl()){
17             if(b.c>=a.c){
18                 double k=a.d-(a.c-b.a)*b.xl();
19                 k=max(k,0.);
20                 return p+k; 
21             }
22             double k=a.d-b.d-(a.c-b.c)*a.xl();
23             k=max(k,0.);
24             return p+k;
25         }else{
26             if(b.a<=a.a) return p;
27             double k=a.d-(a.c-b.a)*a.xl();
28             k=max(k,0.);
29             return p+k;
30         }
31     }
32 }a[M],s[M];
33 int n,p[M]={0};
34 int main(){
35     scanf("%d",&n);
36     for(int i=1;i<=n;i++){
37         double x,y,z; cin>>x>>y>>z;
38         a[i]=node(y,0,z,x);
39     }
40     for(int i=1;i<=n;i++) p[i]=i;
41     double minn=1e10;
42     while(1){
43         memset(s,0,sizeof(s));
44         s[0]=node(1e20,0,1e21,0);
45         for(int i=1;i<=n;i++){
46             double maxn=0;
47             for(int j=0;j<i;j++) 
48             maxn=max(maxn,s[j]-a[p[i]]);
49             s[i]=node(a[p[i]].a,maxn,a[p[i]].c,a[p[i]].d+maxn);
50         }
51         double maxn=0;
52         for(int i=1;i<=n;i++) maxn=max(maxn,s[i].d);
53         if(maxn<minn)
54         minn=min(minn,maxn);
55         if(!next_permutation(p+1,p+n+1)) break;
56     }
57     printf("%.0lf\n",minn);
58 }

 

转载于:https://www.cnblogs.com/xiefengze1/p/9246317.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值