NC20464 [ZJOI2006]BOWL 碗的叠放(全排列枚举)

题目链接

题意:
有 n 个 倒 梯 形 , 上 宽 下 窄 的 碗 有n个倒梯形,上宽下窄的碗 n
他 们 的 下 底 边 是 r 1 , 上 底 边 是 r 2 , 高 是 h 他们的下底边是r1,上底边是r2,高是h r1,r2,h
求 出 碗 叠 放 的 最 低 高 度 求出碗叠放的最低高度
题解:
n < = 10 n<=10 n<=10
所 以 直 接 枚 举 放 碗 顺 序 , 找 一 下 怎 么 能 最 低 所以直接枚举放碗顺序,找一下怎么能最低

然 后 考 虑 放 碗 的 高 度 然后考虑放碗的高度
可 以 考 虑 的 是 , 把 x 碗 放 到 y 碗 上 , x 碗 的 下 底 的 高 度 可以考虑的是,把x碗放到y碗上,x碗的下底的高度 xyx
第 一 种 情 况 第一种情况
在这里插入图片描述
很 明 显 , x 的 下 底 大 于 y 的 上 底 很明显,x的下底大于y的上底 xy
所 以 x 的 下 底 高 度 直 接 是 h y 所以x的下底高度直接是h_y xhy

第 二 种 情 况 第二种情况
在这里插入图片描述
x 的 上 底 小 于 y 的 下 底 , 肯 定 是 直 接 能 放 进 y 里 的 x的上底小于y的下底,肯定是直接能放进y里的 xyy
所 以 这 个 时 候 x 的 下 底 高 度 就 是 0 所以这个时候x的下底高度就是0 x0

第 三 种 情 况 是 x 的 边 斜 率 大 于 等 于 y 第三种情况是x的边斜率大于等于y xy
这 里 又 分 出 来 两 种 情 况 这里又分出来两种情况
在这里插入图片描述
在这里插入图片描述
根 据 图 片 也 很 容 易 看 出 根据图片也很容易看出
分 别 是 x 的 下 底 大 于 和 小 于 y 的 下 底 的 情 况 分别是x的下底大于和小于y的下底的情况 xy
小 于 的 时 候 很 明 显 , 是 0 小于的时候很明显,是0 0
大 于 的 时 候 就 要 考 虑 一 下 了 大于的时候就要考虑一下了
假 设 x 的 下 底 高 度 为 h 假设x的下底高度为h xh
那 么 可 以 找 到 一 个 比 例 式 r 2 y − r 1 y h y = r 1 x − r 1 y h 那么可以找到一个比例式\frac{r2_y-r1_y}{h_y}=\frac{r1_x-r1_y}{h} hyr2yr1y=hr1xr1y
其 实 就 是 两 个 斜 率 相 等 列 出 的 式 子 , 这 样 就 可 以 算 出 h 了 其实就是两个斜率相等列出的式子,这样就可以算出h了 h

第 四 种 情 况 , 就 是 x 的 斜 率 小 于 y 第四种情况,就是x的斜率小于y xy
这 里 也 有 两 种 情 况 这里也有两种情况
在这里插入图片描述
在这里插入图片描述
分 别 是 x 的 上 底 大 于 和 小 于 y 的 上 底 分别是x的上底大于和小于y的上底 xy
大 于 的 情 况 就 是 用 h y 减 去 y 的 上 底 到 x 的 下 底 的 距 离 大于的情况就是用h_y减去y的上底到x的下底的距离 hyyx
用 类 似 刚 才 的 斜 率 公 式 就 可 以 算 出 来 用类似刚才的斜率公式就可以算出来
最 终 下 底 高 度 为 h y − h x ∗ r 2 y − r 1 x r 2 x − r 1 x 最终下底高度为h_y-h_x*\frac{r2_y-r1_x}{r2_x-r1_x} hyhxr2xr1xr2yr1x

小 于 的 情 况 就 是 用 x 的 上 底 到 y 的 下 底 的 距 离 减 去 h x 小于的情况就是用x的上底到y的下底的距离减去h_x xyhx
最 终 为 h y ∗ r 2 x − r 1 y r 2 y − r 1 y − h x 最终为h_y*\frac{r2_x-r1_y}{r2_y-r1_y}-h_x hyr2yr1yr2xr1yhx
到 这 就 把 两 两 组 合 全 部 的 下 底 高 度 算 出 来 了 到这就把两两组合全部的下底高度算出来了

然 后 对 于 每 种 排 列 , 一 个 一 个 放 , 放 的 时 候 找 当 前 放 的 碗 然后对于每种排列,一个一个放,放的时候找当前放的碗
和 前 面 每 个 组 合 一 下 看 看 最 高 是 哪 一 个 , 这 就 是 当 前 的 高 度 和前面每个组合一下看看最高是哪一个,这就是当前的高度
由 于 算 出 的 是 下 底 高 度 , 最 后 结 果 要 加 上 当 前 碗 的 高 度 由于算出的是下底高度,最后结果要加上当前碗的高度

AC代码

/*
    Author : zzugzx
    Lang : C++
    Blog : blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const double eps = 1e-10;
const double pi = acos(-1.0);
const int maxn = 1e6 + 10;
//const int N = 1e3 + 10;
const ll inf = 0x3f3f3f3f;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
double h[maxn], r1[maxn], r2[maxn], tmp[maxn];
double calc(int x, int y) {
    if (r1[x] > r2[y])
        return h[y];
    if (r2[x] < r1[y])
        return 0;
    if ((r2[x] - r1[x]) * h[y] <= (r2[y] - r1[y]) * h[x]) {
        if (r1[x] <= r1[y]) return 0;
        return h[y] * (r1[x] - r1[y]) / (r2[y] - r1[y]);
    }
    if (r2[x] > r2[y])
        return max(0.0, h[y] - h[x] * (r2[y] - r1[x]) / (r2[x] - r1[x]));
    return max(0.0, h[y] * (r2[x] - r1[y]) / (r2[y] - r1[y]) - h[x]);
}
int id[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
//  freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> h[i] >> r1[i] >> r2[i], id[i] = i;
    double ans = inf, res = 0;
    do{
        res = 0;
        for (int i = 1; i <= n; i++){
            tmp[i] = 0;
            for (int j = 1; j < i; j++)
                tmp[i] = max(tmp[i], tmp[j] + calc(id[i], id[j]));
            res = max(tmp[i] + h[id[i]], res);
        }
        ans = min(ans, res);
    }while(next_permutation(id + 1, id + 1 + n));
    cout << (int)(ans + 0.5);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值