题意

给定一棵满二叉树,每个叶节点有一个状态0/10/10/1,对于每两个叶节点i,ji,ji,j,如果这两个叶节点状态相同但他们的LCALCALCA所管辖的子树中的与他们状态相同的叶节点个数较少(少于1/21/21/2),则会产生2fij2f_{ij}2fij​的代价,如果状态不同,则产生fijf_{ij}fij​的代价,如果状态相同且LCALCALCA管辖子树中与他们状态相同叶节点个数较多,则不产生代价,现在每个节点可以变更状态,但变更状态也有自己的代价,求最小总代价 。

题解

在满二叉树上暴力枚举这个点子树中是000多还是111多,然后递归下去DPDPDP合并。时间复杂度是O(2n⋅2n⋅n)O(2^n\cdot 2^n\cdot n)O(2n⋅2n⋅n)的。对于每一个叶子结点,到根的路径最长只有nnn,所有情况就是2n2^n2n,所以所有叶子节点加起来的时间复杂度是2n⋅2n2^n\cdot 2^n2n⋅2n,由于还要枚举这条路径上的点算代价,所以就再乘个nnn。

费用的计算方法就是:

对于点对(i,j)(i,j)(i,j)的贡献,如果LCALCALCA和iii异色,费用就加上一个fijf_{ij}fij​,如果LCALCALCA和jjj异色,就再加上一个fijf_{ij}fij​。可以发现这样算出来的答案恰好符合题意。LCALCALCA的颜色就表示子树下面111多还是000多,这个是暴力枚举的。

具体实现看代码。

CODE

dp[i][j]dp[i][j]dp[i][j]表示在iii的子树里选了jjj个111的最小费用。

#pragma GCC optimize (3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 2060;
const LL INF = 1ll<<40;
int f[MAXN][2], n, all, a[MAXN];
LL dp[MAXN][MAXN], cst[MAXN][12];
bool clr[12];
void dfs(int x, int dep) {
for(int i = 0; i <= all; ++i) dp[x][i] = INF;
if(dep == n) {
dp[x][0] = f[x-all][0];
dp[x][1] = f[x-all][1];
for(int i = 0; i < n; ++i) dp[x][clr[i]^1] += cst[x-all][i];
return;
}
int half = 1<<(n-dep-1);
clr[dep] = 0; dfs(x<<1, dep+1), dfs(x<<1|1, dep+1);
for(int i = 0; i <= half; ++i)
for(int j = 0; i+j <= half; ++j)
dp[x][i+j] = min(dp[x][i+j], dp[x<<1][i] + dp[x<<1|1][j]); clr[dep] = 1; dfs(x<<1, dep+1), dfs(x<<1|1, dep+1);
for(int i = 0; i <= half; ++i)
for(int j = half+1-i; j <= half; ++j)
dp[x][i+j] = min(dp[x][i+j], dp[x<<1][i] + dp[x<<1|1][j]);
}
int lca_dep(int u, int v) {
for(int i = n-1; i >= 0; --i) if((u>>i) != (v>>i)) return n-i-1;
}
int main () {
scanf("%d", &n); all = 1<<n;
for(int i = 0; i < all; ++i) scanf("%d", &a[i]);
for(int i = 0; i < all; ++i) f[i][a[i]] = 0, scanf("%d", &f[i][a[i]^1]);
for(int i = 0; i < all; ++i)
for(int j = i+1; j < all; ++j) {
int k = lca_dep(i, j), v; scanf("%d", &v);
cst[i][k] += v, cst[j][k] += v;
}
dfs(1, 0);
printf("%lld\n", *min_element(dp[1], dp[1] + all + 1));
}

BZOJ 1495 [NOI2006]网络收费(暴力DP)的更多相关文章

  1. 【BZOJ1495】[NOI2006]网络收费 暴力+DP

    [BZOJ1495][NOI2006]网络收费 Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的一点就是网络本身有 ...

  2. 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp

    LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...

  3. 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp

    题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的 ...

  4. 并不对劲的[noi2006]网络收费

    题目略长,就从大视野上复制了. 听上去好像费用流,然而…… ***************************表示略长的题目的分界线************************ 1495: [ ...

  5. BZOJ_1495_[NOI2006]网络收费_树形DP

    BZOJ_1495_[NOI2006]网络收费_树形DP Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而, 不可忽视的一点就 ...

  6. 洛谷 P4297 [NOI2006]网络收费

    P4297 [NOI2006]网络收费 题目背景 noi2006 day1t1 题目描述 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的 ...

  7. 【简】题解 P4297 [NOI2006]网络收费

    传送门:P4297 [NOI2006]网络收费 题目大意: 给定一棵满二叉树,每个叶节点有一个状态(0,1),任选两个叶节点,如果这两个叶节点状态相同但他们的LCA所管辖的子树中的与他们状态相同的叶节 ...

  8. BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】

    题目链接 BZOJ1495 题解 观察表格,实际上就是分\(A\)多和\(B\)两种情况,分别对应每个点选\(A\)权值或者\(B\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...

  9. bzoj1495 [NOI2006]网络收费 复杂度分析+树上背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1495 题解 通过观察可以发现,对于一个 \(lca\),如果 \(nA \leq nB\),那 ...

随机推荐

  1. 【算法】js实现最短时间走完不同速度的路程

    题目: 现在有一条公路,起点是0公里,终点是100公里.这条公路被划分为N段,每一段有不同的限速.现在他们从A公里处开始,到B公里处结束.请帮他们计算在不超过限速的情况下,最少需要多少时间完成这段路程 ...

  2. Win10 将本地连接设置为按流量计费网络

    在Win10中默认是不允许用户将本地连接设置为按流量计费网络的,不过我们可以通过修改注册表的方式来实现. 将本地连接设置为按流量计费网络后,Windows更新将不会自动下载.同样,Windows应用商 ...

  3. mysql数据库,数据表,数据的增删查改语句

    查询mysql支持的引擎 show engines; 查询mysql支持的字符集 show character set; 设置mysql默认存储引擎 set default_storage_engin ...

  4. vs2017环境下python包的安装

    1)---vs已经下载了的才适用 1,鼠标放在右侧窗口python环境那里(如没有窗口,可点击最上方的“窗口”-“重置窗口”) 2,右键然后点击“查看所有python环境”,会弹出当前默认的环境(高亮 ...

  5. Map、FlatMap 和 Reduce

    Map 作用是生成一个新数组,遍历原数组,将每个元素拿出来做一些变换然后 append 到新的数组中. [1, 2, 3].map((v) => v + 1) // -> [2, 3, 4 ...

  6. Spring Cloud Alibaba学习笔记(8) - RocketMQ术语与概念

    Topic 一类消息的集合,RocketMQ的基本订阅单位 部署结构 Name Server Name Server 为 producer 和 consumer 提供路由信息. 相对来说,namese ...

  7. 如何判断当前修改过的datatable的某一列值是否为int型或double类型

    如何判断当前修改过的datatable的某一列值是否为int型或double类型 今天在做datatable数据验证时碰到要对datatable的列数据进行数据类型校验,因此记录一下本人校验的方法,如 ...

  8. C#判断字符串中含有多少个汉字

    private void button1_Click(object sender, EventArgs e) { ArrayList itemList = new ArrayList(); CharE ...

  9. 【转载】C#使用Split函数根据特定分隔符分割字符串

    在C#程序开发过程中,很多时候可能需要将字符串根据特定的分割字符分割成字符或者List集合,例如根据逗号将字符串分割为数组,或者根据竖线将字符串分割成数组,C#中提供了Split()函数来快速将字符串 ...

  10. English-培训2-五大句型