poj2767

题意:一些圆台形(中空,厚度忽略不计)的碗,罗在一起,问最小高度是多少。

分析:枚举所有情况,每放一个碗,就要记录其碗底的高度。记录碗底高度的方法是,枚举下面所有的碗,把想象中把这个碗与下面的碗直接叠放在一起,看碗底的高度,取最大值,得到这个碗底的真实高度。每次罗起了所有的碗,就根据每个碗碗底的高度计算其碗顶的高度,并取最大值,即为本次罗碗的高度。不断更新最终结果,取最小值。

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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2117304.html