当前位置:网站首页>【luogu AT2230】Water Distribution(状压DP)(最小生成树)
【luogu AT2230】Water Distribution(状压DP)(最小生成树)
2022-07-16 03:50:00 【SSL_TJH】
Water Distribution
题目链接:luogu AT2230
题目大意
给你一个二维平面上的一些点,每个点有初始水量。
然后你可以两个点之间运水,水量没有上限,但是每次运水会损失掉两点距离长度的水。
然后要你通过操作使得所有点的水量的最小值最大。
思路
有个地方很卡精度我不说是谁。
考虑有一些性质,首先发现答案一定是可以被分成若干个连通块,每个连通块之间补水。
然后就会有一个显然的性质是补水的通道一定组成生成树,毕竟出现环一定有一边不优(一样那也无所谓)。
那再有这个边肯定是只有一边走的(总不可能运过去发现没用运回来吧)
所以这个连通块稳定下来之后,每个点的水量是固定的: s u m − m s t m \dfrac{sum-mst}{m} msum−mst
(三个东西分别是点权和,最小生成树边权和,连通块点数)
然后至于若干个集合之间肯定取最小的作为答案,你就状压 DP 一下就可以了。
(然后 luogu 小卡精度,反正我要 long double)
代码
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 15;
const int eps = 1e-10;
struct node {
int x, y, a;
}a[N];
struct line {
int x, y; long double dis;
}xl[N * N];
int n, fa[N];
long double dis[N][N], mst[1 << N], sum[1 << N], f[1 << N], g[1 << N];
bool cmp(line x, line y) {
return x.dis - y.dis < eps;
}
int find(int now) {
return fa[now] == now ? now : fa[now] = find(fa[now]);
}
int main() {
// freopen("water.in", "r", stdin);
// freopen("water.out", "w", stdout);
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].a);
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dis[i][j] = sqrt((long double)(a[i].x - a[j].x) * (a[i].x - a[j].x) + (long double)(a[i].y - a[j].y) * (a[i].y - a[j].y));
for (int i = 1; i < (1 << n); i++) {
int m = 0, bm = 0;
for (int j = 0; j < n; j++) if ((i >> j) & 1) {
m++; sum[i] += 1.0 * a[j].a;
for (int k = 0; k < j; k++) if ((i >> k) & 1) {
xl[++bm] = (line){
j, k, dis[j][k]};
}
}
for (int j = 0; j < n; j++) fa[j] = j;
sort(xl + 1, xl + bm + 1, cmp);
for (int j = 1; j <= bm; j++) {
if (find(xl[j].x) != find(xl[j].y)) fa[find(xl[j].x)] = find(xl[j].y), mst[i] += xl[j].dis;
}
f[i] = max((sum[i] - mst[i]) / m, (long double)0.0);
}
g[0] = 1e18;
for (int i = 1; i < (1 << n); i++) {
for (int j = i; j; j = i & (j - 1))//枚举子集
g[i] = max(g[i], min(f[j], g[i ^ j]));
}
printf("%.10Lf", g[(1 << n) - 1]);
return 0;
}
边栏推荐
- DPR-34、AC220V双位置继电器
- Brush questions in summer vacation
- EXCEL,选择数据如何选择合适的图表?
- 【深度学习】《动手学深度学习》环境配置
- The static variable looks a little dizzy, and the GDB assembly is awake
- [TinyML]NetAug:Network Augmentation for Tiny Deep Learning
- 【luogu P2151】HH去散步(DP)(矩阵乘法)
- Zhongang Mining: Fluorite guarantees the supply of fluorine in new energy industry
- 快速上手Jupyter Notebook
- High frequency interview questions -- subarray with sum K
猜你喜欢

静态路由技术

Research progress of transfer learning in medical image classification

singan:learning a generative model from a single natural image

基于AMDP的BW转换专家例程

Efcore - entry and attach
![[TinyML]NetAug:Network Augmentation for Tiny Deep Learning](/img/b4/e4d6d2394b6e1ad7bcfdc9ae984913.png)
[TinyML]NetAug:Network Augmentation for Tiny Deep Learning

How to generate non repeated random numbers in Excel, multi method + principle

TCP/IP之常用协议

Recursively solve the traversal of binary trees (often test basic examples)

Aomei Easy clone system disk backup
随机推荐
Research progress of transfer learning in medical image classification
求水仙花数
[deep learning] environment configuration of hands-on learning and deep learning
众昂矿业:萤石保障新能源工业氟元素供应
剑指 Offer 32 - II. 从上到下打印二叉树 II for_in range()
Excel, how to choose the right chart?
ACL技术
MulterError: Unexpected field
"Harmonyos" explore harmonyos applications
[machine learning] decision tree
Dynamic cool 404 page source code
Dual position relay dls-5/1
Get started quickly, Jupiter notebook
Task-Customized Self-Supervised Pre-training with Scalable Dynamic Routing
Description of common operators in Halcon 3D
QA robot section 1 - Introduction
为什么 Qt Creator 的编译如此之慢?
MATLAB学习第二天(基础语法、变量、命令以及新建自己文件)
The static variable looks a little dizzy, and the GDB assembly is awake
DzzOffice_flowplayer播放器更改