【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所管辖的子树中的与他们状态相同的叶节 ...
随机推荐
- hibernate中一些属性对操作的影响
1 inverse,在一对多中使用,表示是否有关联关系控制权.对于保存.删除数据有影响. 2 cascade,表示级联操作 save-update 表示级联保存和更新 delete 表示级联删除 al ...
- IronPython使用
C#: class Program { static void Main(string[] args) { ScriptEngine engine = Python.CreateEngine(); S ...
- Atitit.数据库事务隔离级别 attilax 总结
Atitit.数据库事务隔离级别 1. 事务隔离级别的作用 1 2. 在的隔离级别 2 3. 常见数据库的默认管理级别 3 1. 事务隔离级别的作用 较低的隔离级别可以增强许多用户同时访问数据的能力, ...
- java的装箱拆箱是什么?
是什么? 自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱. 为什么 把 ...
- HDU 2844 Coin 多重背包
Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- storyboard三种sugue 和 跳转场景的三种方式 以及控制器之间的传值
Storyboard引入了2个概念:1. scene:一个场景,由一个viewController和相关的xib表示. 2. segue:在这是用于连接scenes,其有多种类型,iphone包括:P ...
- 基础地图Android SDK
开发者可利用SDK提供的接口,使用百度为您提供的基础地图数据.目前百度地图SDK所提供的地图等级为3-21级,所包含的信息有建筑物.道路.河流.学校.公园等内容. V3.7.0起,地图支持缩放至21级 ...
- gdb,程序调试助手
启动GDB:(其中我的app是编译之后的可执行文件) 退出命令:quit或者简写q 帮助获取: gdb通过完备的在线帮助,使我们使用起来更加方便.所有的帮助信息都是通过help命令获得的,运行help ...
- 基于HTML5堆木头游戏
今天要来分享一款很经典的HTML5游戏——堆木头游戏,这款游戏的玩法是将木头堆积起来,多出的部分将被切除,直到下一根木头无法堆放为止.这款HTML5游戏的难点在于待堆放的木头是移动的,因此需要你很好的 ...
- 跟着百度学习php之ThinkPHP的运行流程-2
Thinkphp为了提高编译的效率,第一次运行的时候thinkphp会把文件全部编译到temp目录下的~runtime.php文件,在第二次运行的时候会直接读取这个文件.所以我们在线下自己写代码测试的 ...