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


Input
Output
你的程序只需要向输出文件输出一个整数,表示NS中学支付给网络公司的最小总费用。(单位:元)
Sample Input
1 0 1 0
2 2 10 9
10 1 2
2 1
3
Sample Output
HINT
【样例说明】 将1号用户的付费方式由B改为A,NS中学支付给网络公司的费用达到最小
题解:先观察表格,发现当nA<nB时,我们可以将选A看成系数为1,选B看成系数为0,这样就可以将点对的贡献拆开来考虑。为此我们预处理cost[i][j],表示i与所有和i的lca深度为j的点构成的点对费用之和,这样我们就相当于将花费都放到了叶子节点处。
但是我们需要知道每个点是nA<nB还是nA>=nB才能确定叶子节点的费用,但由于是完全二叉树,所以我们可以枚举每个节点是nA<nB还是nA>=nB,然后就能确定叶子节点的取A或B的费用,接着用f[x][y]表示x子树中有y个B,其余都是A的最小费用,那么从将一个非叶子节点的两个儿子的DP值进行背包合并便得到了该点的DP值。由于我们已经钦定了该点是nA<nB或是nA>=nB,所以我们在DP时将不合法的状态去掉即可。
以上做法看起来可能比较暴力,不过实际复杂度呢?$T(n)=4(n-1)+2^{2n}$,所以每一层的复杂度都是$O(2^{2n})$的,一共log层;而搜一次叶子节点消耗的时间是n,每个叶子都要被搜到$O(2^n)$次,一共$2^n$个叶子,所以两个地方的复杂度都是$O(2^{2n}n)$的。
然而正解是把我的暴力改成状压。。。都差不多。
goubiGXZ交我程序还加读入优化拿Rank1。
#include <cstdio>
#include <cstring>
#include <iostream>
#define ls x<<1
#define rs x<<1|1
using namespace std;
const int maxn=2100;
typedef long long ll;
int n;
ll ans;
int tp[maxn],B[20],s[20];
ll cost[maxn][12],f[maxn][maxn],C[maxn][2];
inline int lca(int a,int b)
{
int i;
for(i=n-1;i>=0;i--) if((a>>i)!=(b>>i)) break;
return n-i-1;
}
inline int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
void dfs(int x,int dep)
{
if(dep==n)
{
f[x][0]=C[x-B[n]][0];
f[x][1]=C[x-B[n]][1];
for(int i=0;i<dep;i++) f[x][s[i]^1]+=cost[x-B[n]][i];
return ;
}
s[dep]=0;
memset(f[x],0x3f,sizeof(f[x][0])*(B[n-dep]+1));
dfs(ls,dep+1),dfs(rs,dep+1);
for(int i=0;i<=B[n-dep-1];i++) for(int j=0;i+j<=B[n-dep-1];j++) f[x][i+j]=min(f[x][i+j],f[ls][i]+f[rs][j]);
s[dep]=1;
dfs(ls,dep+1),dfs(rs,dep+1);
for(int i=1;i<=B[n-dep-1];i++) for(int j=B[n-dep-1]+1-i;j<=B[n-dep-1];j++) f[x][i+j]=min(f[x][i+j],f[ls][i]+f[rs][j]);
}
int main()
{
//freopen("network.in","r",stdin);
//freopen("network.out","w",stdout);
n=rd();
int i,j,v,a;
for(i=0;i<=n;i++) B[i]=1<<i;
for(i=0;i<B[n];i++) tp[i]=rd();
for(i=0;i<B[n];i++) C[i][tp[i]]=0,C[i][tp[i]^1]=rd();
for(i=0;i<B[n];i++) for(j=i+1;j<B[n];j++)
{
a=lca(i,j),v=rd();
cost[i][a]+=v,cost[j][a]+=v;
}
dfs(1,0);
ans=1ll<<60;
for(i=0;i<=B[n];i++) ans=min(ans,f[1][i]);
printf("%lld",ans);
return 0;
}
【BZOJ1495】[NOI2006]网络收费 暴力+DP的更多相关文章
- 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp
LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...
- 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp
题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的 ...
- BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】
题目链接 BZOJ1495 题解 观察表格,实际上就是分\(A\)多和\(B\)两种情况,分别对应每个点选\(A\)权值或者\(B\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...
- BZOJ1495 [NOI2006]网络收费
题意 传送门 MY市NS中学,大概是绵阳市南山中学. 分析 参照Maxwei_wzj的题解. 因为成对的贡献比较难做,我们尝试把贡献算到每一个叶子节点上.我们发现按照题目中的收费方式,它等价于对于每棵 ...
- bzoj1495 [NOI2006]网络收费 复杂度分析+树上背包
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1495 题解 通过观察可以发现,对于一个 \(lca\),如果 \(nA \leq nB\),那 ...
- BZOJ_1495_[NOI2006]网络收费_树形DP
BZOJ_1495_[NOI2006]网络收费_树形DP Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而, 不可忽视的一点就 ...
- 洛谷 P4297 [NOI2006]网络收费
P4297 [NOI2006]网络收费 题目背景 noi2006 day1t1 题目描述 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的 ...
- 并不对劲的[noi2006]网络收费
题目略长,就从大视野上复制了. 听上去好像费用流,然而…… ***************************表示略长的题目的分界线************************ 1495: [ ...
- 【简】题解 P4297 [NOI2006]网络收费
传送门:P4297 [NOI2006]网络收费 题目大意: 给定一棵满二叉树,每个叶节点有一个状态(0,1),任选两个叶节点,如果这两个叶节点状态相同但他们的LCA所管辖的子树中的与他们状态相同的叶节 ...
随机推荐
- 【C语言】二维数组中的查找,杨氏矩阵
//二维数组中的查找,杨氏矩阵 //在一个二维数组中,每行都依照从左到右的递增的顺序排序.每列都依照从上到下递增的顺序排序. //请完毕一个函数.输入这种一个数组和一个数,推断数组中是否包括这个数. ...
- PySpark的DataFrame处理方法
转:https://blog.csdn.net/weimingyu945/article/details/77981884 感谢! ---------------------------------- ...
- mysql date and time type ---- mysql 时间&日期 类型详解
mysql 中支持用多种方式来表示时间与日期 一.mysql 中能表示时间与日期的数据类型: 1.表示年 ) -- 最好不要用这个数据类型.对于年份的取值中有[1901 --> 2155] + ...
- 《LAMP系统工程师实用教程》读书笔记(一)- linux常用命令
图书馆看到就借回来啦,这本书虽然其貌不扬,对新手还是挺棒的.来学下shell脚本和php. 把书上不熟悉的命令和选项记录下. mkdir -v创建文件夹并返回信息 mkdir -m创建文件夹并设定权限 ...
- ssm开发系的统架构图
- js 去html 标签
var stylereg = /style\=".+?"/g //去style样式 var alltagreg = /<[^>]*>/g //去除全部标签 var ...
- js去掉双引号
替换: d = d.replace("\"","").replace("\"",""); 全部替换: ...
- Unix系统编程()虚拟内存管理
在之前学到过进程的内存布局中忽略了一个事实:这一布局存在于虚拟文件中. 因为对虚拟内存的理解将有助于后续对fork系统调用.共享内存和映射文件之类的主题阐述,这里还要学习一下有关虚拟内存的详细内容. ...
- [system]c/c++调用cat命令
因为cat并不是一个带返回的命令,而是输出到标准输出.所以使用system("cat /sys/class/gpio/...."); 得不到我们想要的结果. 下面的/bin/ls同 ...
- 介绍编译的less的几种IDE工具
介绍编译的less的两种IDE工具 现在css预编译越来越普及了,著名的有less.sass.stylus等等等等.功能上基本上都是大同小异.这些个玩意儿主要表达的意思就是:“像编程一样的编写你的cs ...