题意:一些圆台形(中空,厚度忽略不计)的碗,罗在一起,问最小高度是多少。
分析:枚举所有情况,每放一个碗,就要记录其碗底的高度。记录碗底高度的方法是,枚举下面所有的碗,把想象中把这个碗与下面的碗直接叠放在一起,看碗底的高度,取最大值,得到这个碗底的真实高度。每次罗起了所有的碗,就根据每个碗碗底的高度计算其碗顶的高度,并取最大值,即为本次罗碗的高度。不断更新最终结果,取最小值。
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 10
struct Bowl
{
int r1, r2, h;
} bowl[maxn];
bool vis[maxn];
int sel[maxn];
int ans, n;
double height[maxn];
void input()
{
scanf("%d", &n);
for (int i =0; i < n; i++)
scanf("%d%d%d", &bowl[i].h, &bowl[i].r1, &bowl[i].r2);
}
double inc(int a, int b)
{
if (bowl[b].r1 >= bowl[a].r2)
return bowl[a].h;
if (bowl[b].r2 <= bowl[a].r1)
return0;
double ret =0;
if (bowl[b].r1 >= bowl[a].r1)
ret = max(ret, bowl[a].h * (bowl[b].r1 - bowl[a].r1) *1.0/ (bowl[a].r2
- bowl[a].r1));
if (bowl[b].r2 <= bowl[a].r2)
ret = max(ret, bowl[a].h * (bowl[b].r2 - bowl[a].r1) *1.0/ (bowl[a].r2
- bowl[a].r1) - bowl[b].h);
if (bowl[b].r2 > bowl[a].r2)
ret = max(ret, bowl[a].h - bowl[b].h * (bowl[a].r2 - bowl[b].r1) *1.0
/ (bowl[b].r2 - bowl[b].r1));
return ret;
}
void find(int x, int a)
{
height[x] =0;
for (int i =0; i < x; i++)
height[x] = max(height[x], height[i] + inc(sel[i], a));
}
void dfs(int step)
{
if (step == n)
{
int temp =0;
for (int i =0; i < n; i++)
temp = max(temp, (int) (height[i] + bowl[sel[i]].h));
ans = min(ans, temp);
return;
}
for (int i =0; i < n; i++)
if (!vis[i])
{
vis[i] =true;
sel[step] = i;
find(step, i);
dfs(step +1);
vis[i] =false;
}
}
int main()
{
//freopen("t.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--)
{
input();
memset(vis, 0, sizeof(vis));
ans =0x3f3f3f3f;
dfs(0);
printf("%d\n", ans);
}
return0;
}