当前位置: 首页 > news >正文

UVa 1354 Mobile Computing

题目分析

问题描述

在一个二维星球上,人们用石头制作移动雕塑(mobile\texttt{mobile}mobile)。一个 mobile\texttt{mobile}mobile 的定义如下:

  • 一个石头用一根绳子悬挂;或者
  • 一根长度为 111 的杆,两端各悬挂一个子 mobile\texttt{mobile}mobile,杆悬挂在两个子 mobile\texttt{mobile}mobile 的整体重心处。

当两个子 mobile\texttt{mobile}mobile 的重量分别为 nnnmmm,它们距离重心的距离分别为 aaabbb 时,满足力矩平衡方程:
n×a=m×bn \times a = m \times bn×a=m×b

给定石头的重量和房间的宽度,要求设计一个使用所有石头的 mobile\texttt{mobile}mobile,其宽度小于房间宽度,并且要使得这个宽度尽可能大。

输入格式

  • 第一行:数据集数量 TTT
  • 每个数据集:
    • 房间宽度 rrr0<r<100 < r < 100<r<10
    • 石头数量 sss1≤s≤61 \leq s \leq 61s6
    • sss 个石头的重量 wiw_iwi1≤wi≤10001 \leq w_i \leq 10001wi1000

输出格式

对于每个数据集,输出可能的最大宽度(精度误差不超过 10−810^{-8}108),如果没有满足条件的 mobile\texttt{mobile}mobile,输出 −1-11

解题思路

关键观察

  1. 力矩平衡条件:当合并两个子树时,设左子树重量为 nnn,右子树重量为 mmm,则左子树重心到整体重心的距离为:
    a=mn+ma = \frac{m}{n + m}a=n+mm
    右子树重心到整体重心的距离为:
    b=nn+mb = \frac{n}{n + m}b=n+mn

  2. 宽度计算mobile\texttt{mobile}mobile 的总宽度等于悬挂点到最左端的距离加上悬挂点到最右端的距离。

  3. 递归结构:每个子树可以用一个三元组 (weight,left,right)(weight, left, right)(weight,left,right) 表示:

    • weightweightweight:子树的总重量
    • leftleftleft:子树重心到最左端的距离
    • rightrightright:子树重心到最右端的距离

算法设计

由于 s≤6s \leq 6s6,我们可以使用状态压缩动态规划结合深度优先搜索:

  1. 状态表示:用位掩码 maskmaskmask 表示使用的石头集合

  2. 状态存储dp[mask]dp[mask]dp[mask] 存储该集合能形成的所有 (weight,left,right)(weight, left, right)(weight,left,right) 三元组

  3. 初始状态:单个石头 iii 的状态为 (wi,0,0)(w_i, 0, 0)(wi,0,0)

  4. 状态转移:对于每个 maskmaskmask,枚举其所有非空真子集 leftMaskleftMaskleftMask,计算:

    • rightMask=mask⊕leftMaskrightMask = mask \oplus leftMaskrightMask=maskleftMask
    • 对于 dp[leftMask]dp[leftMask]dp[leftMask]dp[rightMask]dp[rightMask]dp[rightMask] 中的每对三元组,计算合并后的新状态
  5. 合并计算

    • 总重量:weight=L.weight+R.weightweight = L.weight + R.weightweight=L.weight+R.weight
    • 距离:a=R.weightweighta = \frac{R.weight}{weight}a=weightR.weight, b=L.weightweightb = \frac{L.weight}{weight}b=weightL.weight
    • 左半宽度:leftWidth=max⁡(a+L.left,R.left−b)leftWidth = \max(a + L.left, R.left - b)leftWidth=max(a+L.left,R.leftb)
    • 右半宽度:rightWidth=max⁡(b+R.right,L.right−a)rightWidth = \max(b + R.right, L.right - a)rightWidth=max(b+R.right,L.righta)

复杂度分析

  • 状态数:2s=642^s = 642s=64
  • 每个状态的三元组数量在最坏情况下可能达到 C(s)C(s)C(s)(卡特兰数),但由于 s≤6s \leq 6s6,实际可接受
  • 总体复杂度在合理范围内

代码实现

// Mobile Computing
// UVa ID: 1354
// Verdict: Accepted
// Submission Date: 2025-10-23
// UVa Run Time: 0.000s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include <bits/stdc++.h>using namespace std;// 表示一个子树的状态:重量、左半宽度、右半宽度
struct Node {double weight, left, right;Node(double w, double l, double r) : weight(w), left(l), right(r) {}
};vector<Node> dp[1 << 6];  // dp[mask] 存储该掩码对应的所有可能子树状态
int s;                    // 石头数量
vector<int> w;            // 石头重量
double room;              // 房间宽度
bool visited[1 << 6];     // 标记状态是否已计算// 深度优先搜索计算所有可能的子树组合
void dfs(int mask) {if (visited[mask]) return;  // 已计算过,直接返回visited[mask] = true;// 单个石头的情况if (__builtin_popcount(mask) == 1) {int i = __builtin_ctz(mask);  // 找到最低位的 1 对应的石头索引dp[mask].push_back(Node(w[i], 0.0, 0.0));return;}// 枚举所有非空真子集进行合并for (int leftMask = (mask - 1) & mask; leftMask > 0; leftMask = (leftMask - 1) & mask) {int rightMask = mask ^ leftMask;  // 补集作为右子树dfs(leftMask);   // 计算左子树dfs(rightMask);  // 计算右子树// 合并左右子树的所有可能组合for (const Node& L : dp[leftMask]) {for (const Node& R : dp[rightMask]) {double totalWeight = L.weight + R.weight;double a = R.weight / totalWeight;  // 左子树重心到整体重心的距离double b = L.weight / totalWeight;  // 右子树重心到整体重心的距离// 计算新的左右半宽度double leftWidth = max(a + L.left, R.left - b);double rightWidth = max(b + R.right, L.right - a);// 添加新状态dp[mask].push_back(Node(totalWeight, leftWidth, rightWidth));}}}
}int main() {int T;cin >> T;while (T--) {cin >> room;cin >> s;w.resize(s);for (int i = 0; i < s; i++) cin >> w[i];int total = (1 << s) - 1;  // 所有石头的位掩码// 初始化for (int i = 0; i <= total; i++) {dp[i].clear();visited[i] = false;}// 计算所有可能的组合dfs(total);// 寻找满足条件的最大宽度double best = -1.0;for (const Node& nd : dp[total]) {double width = nd.left + nd.right;if (width < room - 1e-9) {  // 考虑浮点精度误差if (width > best) best = width;}}// 输出结果if (best < 0) {cout << "-1\n";} else {cout << fixed << setprecision(15) << best << "\n";}}return 0;
}

总结

本题通过状态压缩动态规划枚举所有可能的子树组合,利用力矩平衡原理和几何关系计算 mobile\texttt{mobile}mobile 的宽度。关键在于将每个子树抽象为 (weight,left,right)(weight, left, right)(weight,left,right) 三元组,这样无论子树内部结构多复杂,都能正确计算出合并后的宽度。算法充分利用了 s≤6s \leq 6s6 的小数据范围,通过位运算高效枚举所有可能状态。

http://www.dtcms.com/a/521882.html

相关文章:

  • 做交互设计的网站网站优化搜索排名
  • 延安网站建设公司电话上海网店代运营外包
  • FastText 从入门到实战:文本分类与词向量迁移
  • 首届中葡农业国际博览会(澳门)影响力几何?将带来哪些新机遇?
  • 怎么设计网站内容工程平台公司做什么的
  • 高并发网站建设什么网站做电气自动化兼职
  • 如何使用IntelliJ IDEA进行Java编程
  • 建设淘宝网站的目的跨境网络专线多少钱一年
  • 建设银行网站查询房贷信息查询广州营销型网站优化
  • 中专网站建设课程自己做的网站如何让百度收录
  • 做视频资源网站有哪些难点住房与城乡建设部
  • 延安网站建设推广国际网站怎么做
  • (Hello-Agents 第四章学习笔记)智能体经典范式构建
  • 动易网站开发的主要技术用dw如何做网站首页
  • SpringBoot-Web开发之视图解析
  • 第十三周前端加密绕过
  • iis 建网站手机访问新开传奇网站迷失版
  • 怎样把网站做成app第一ppt免费模板网
  • 建站平台费用珠海网站建设联系方式
  • 湖南seo网站开发网站服务器租用多少钱
  • 把握三个要点,搭建企业远程技术支持安全体系
  • 推荐一下做图文的网站网址导航怎样推广
  • 建站管理后台中冶东北建设最新网站
  • 网站页面设计知识帝国cms 网站地图标签
  • 企业免费网站模板阜阳手机网站开发
  • 小视频做网站怎么赚钱吗wordpress linode
  • 达州网站建设哪家好wordpress百万并发
  • 《基本函数的统一算法》
  • 四川网站建设企业网站制作ftp 转 wordpress
  • 深圳网站设计兴田德润优惠吗猪八戒网做网站怎么样