【每日一题】BOWL 碗的叠放
[ZJOI2006]BOWL 碗的叠放
https://ac.nowcoder.com/acm/problem/20464
BOWL 碗的叠放
解题思路:
n只有9的大小,因此我们可以枚举碗的拜访顺序。接下来就是判断碗要怎么叠加
我们可以考虑碗的斜边斜率的关系
1)如果两者相等,要么可以放进去要不就不能放进去,
2)如果要放的小于已经放的,同样要放的底边可以放到已放的底边或者不能放到已放的底边,同样是两种情况
3)大于,同样是两种情况就不做图了,自己应该可以画出来
接着就是根据以上可以放的情况来算下底面的高度,找到最小值即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; struct no { double h,r1,r2; }bowl[10]; int id[15]; double temp[15]; double cal(int x,int y) { if(bowl[x].r1>bowl[y].r2) { return bowl[y].h; } if(bowl[x].r2<bowl[y].r1) { return 0; } if((bowl[x].r2-bowl[x].r1)*bowl[y].h<=(bowl[y].r2-bowl[y].r1)*bowl[x].h) { if(bowl[x].r1<=bowl[y].r1) return 0; return bowl[y].h*(bowl[x].r1-bowl[y].r1)/(bowl[y].r2-bowl[y].r1); } if(bowl[x].r2>bowl[y].r2) { return max(0.0,bowl[y].h-bowl[x].h*(bowl[y].r2-bowl[x].r1)/(bowl[x].r2-bowl[x].r1)); } return max(0.0,bowl[y].h*(bowl[x].r2-bowl[y].r1)/(bowl[y].r2-bowl[y].r1)-bowl[x].h); } int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>bowl[i].h>>bowl[i].r1>>bowl[i].r2; id[i]=i; } double ans = 0x3f3f,res=0; do { res=0; for(int i=1;i<=n;i++) { temp[i]=0; for(int j=1;j<i;j++) { temp[i]=max(temp[i],temp[j]+cal(id[i],id[j])); } res=max(temp[i]+bowl[id[i]].h,res); } ans=min(ans,res); }while(next_permutation(id+1,id+1+n)); cout<<(int)(ans+0.5)<<endl; }