题目:
给与你n只碗,每只碗上宽下窄,告诉你上下半径和高度,请你求出n只碗叠放的高度最小为多少?
思路:
由于n<=9,所以可以直接枚举碗的顺序,求高度。
我们可以对两只碗不同情况的叠加情况(从边的斜率和上下半径考虑)进行分析,维护下底高度。
代码:
#include <bits/stdc++.h>
#define inf 1000000007
#define eps 0.000001
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=100005;
struct w
{
double h, r1, r2, k;
}w[15];
int a[15];
double fun(int i,int j)
{
if(w[i].r1>=w[j].r2)
{
return w[j].h;
}
if(w[i].r2<=w[j].r1)
{
return 0;
}
if(w[i].k<w[j].k&&w[i].r2>=w[j].r2)
{
return max(w[j].h-(w[j].r2-w[i].r1)*w[i].k,0.0);
}
if(w[i].k<w[j].k&&w[i].r2<w[j].r2)
{
return max(0.0,(w[i].r2-w[j].r1)*w[j].k-w[i].h);
}
if(w[i].k==w[j].k)
{
if(w[i].r1<=w[j].r1)
{
return 0;
}
else
{
return (w[i].r1-w[j].r1)*w[i].k;
}
}
if(w[i].k>w[j].k&&w[i].r1<=w[j].r1)
{
return 0;
}
if(w[i].k>w[j].k&&w[i].r1>w[j].r1)
{
return (w[i].r1-w[j].r1)*w[j].k;
}
return 0;
}
double tom[15];
int main()
{
int n;
double ans=inf;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
a[i]=i;
scanf("%lf%lf%lf",&w[i].h,&w[i].r1,&w[i].r2);
w[i].k=w[i].h/(w[i].r2-w[i].r1);
}
do
{
double z=0;
for(int i=1;i<=n;i++)
{
tom[i]=0;
for(int j=1;j<i;j++)
{
tom[i]=max(tom[i],tom[j]+fun(a[i],a[j]));
}
z=max(tom[i]+w[a[i]].h,z);
}
ans=min(z,ans);
}while(next_permutation(a+1,a+n+1));
printf("%.0f\n",ans);
return 0;
}

京公网安备 11010502036488号