题目描述
小H有n个碗需要放进橱柜,她希望将他们叠起来放置。你知道每个碗都是规则的圆柱体,并且都是上宽下窄,你已经测量出了每个碗的两个半径及高,请你帮小H找出一种叠放顺序,使得叠放出来的碗堆的高度尽量小,比如:
100%数据满足n < = 9。所有输入的数绝对值不超过1000。
输入描述:
第一行一个整数n,表示碗的数目。
以下n行,每行三个整数h,r1,r2。分别表示碗高及两个半径。其中r1<r2
输出描述:
仅一个数,表示最小的高度。答案四舍五入取整
题解
几何题是我头秃
我们首先分情况讨论一下两个碗放在一起时的状态:(以下讨论的均为放进去的碗的下碗底距离外面的碗的上碗底的高度)
1.如果上面的碗的碗底半径大于下面的碗的碗口半径,直接卡住。
2.如果上面的碗的碗口半径小于下面的碗的碗口半径,可以放进去,但有可能在下底面卡住。
3.下面的碗壁大于上面的碗壁的斜率,算出在哪里是卡住的,再加上即可。
4.下面的碗壁小于等于上面的碗壁的斜率
有了这些关系之后,就需要我们细心的列式子计算,分类讨论了。大家写代码的时候一定要注意,很可能写错一个符号,debug两小时
但要注意的是,每次判断某个碗的高度时要与已经放入的每个碗测一下(因为有些碗放的时候是凹进去的,高度会比外面那只低)
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=2e5+100; /* r1/(h+x)=r2/x r1*x=r2*h+r2*x x=r2*h/(r1-r2); */ int id[10]; double tmp[15]; struct node{ double h,up,down; }s[10]; double gethight(node a,node b){ if(a.up<=b.down){ return 0; } if(a.down>=b.up){ return b.h; } if((a.up-a.down)*b.h<=(b.up-b.down)*a.h){ if(a.down<=b.down){ return 0; } double x=(b.down*b.h)/(b.up-b.down); return (a.down-b.down)*x/b.down; } if(a.up<=b.up){ double x=(b.down*b.h)/(b.up-b.down); return max(0.0,(a.up-b.down)*x/b.down-a.h); } double x=(a.down*a.h)/(a.up-a.down); return max(0.0,b.h-(b.up-a.down)*x/a.down); } //////////////////////////////////////////////////////////////////////// int main(){ ios::sync_with_stdio(false); int n; cin>>n; repi(i,1,n){ cin>>s[i].h>>s[i].down>>s[i].up; id[i]=i; } double ans=1e9,res=0; do{ res=0; repi(i,1,n){ tmp[i]=0; repi(j,1,i-1){ tmp[i]=max(tmp[i],tmp[j]+gethight(s[id[i]],s[id[j]])); } //cout<<"tmp["<<i<<"]="<<tmp[i]<<endl; res=max(tmp[i]+s[id[i]].h,res); //cout<<res<<endl; } ans=min(ans,res); }while(next_permutation(id+1,id+n+1)); cout<<(int)(ans+0.5)<<endl; } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/