zoukankan      html  css  js  c++  java
  • BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】

    题目链接

    BZOJ1495

    题解

    观察表格,实际上就是分(A)多和(B)两种情况,分别对应每个点选(A)权值或者(B)权值,所以成对的权值可以分到每个点上
    所以每个非叶节点实际对应一个状态,表示子树(AB)数量关系
    (f[i][j][s])表示节点(i)子树中选了(j)(A),其祖先的状态为(s)的最小代价
    空间可能开不下,但容易发现(j + s)(2^{N + 1})数量级,所以可以合并到一维
    转移时枚举子树中的(A)即可

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    using namespace std;
    const int maxn = 1050,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int f[maxn << 1][1 << 12],F[maxn][maxn],sta[maxn],C[maxn],L[maxn],R[maxn],M[maxn];
    int n,N;
    void dfs(int u,int l,int r,int d){
    	if (l == r){
    		int maxv = (1 << N) - 1,v;
    		for (int s = 0; s <= maxv; s++){
    			int e = s,sumA = 0,sumB = 0;
    			for (int j = 1; j <= N; j++,e >>= 1){
    				if (e & 1){
    					v = (u >> j);
    					if (l > M[v]) sumB += F[l][M[v]] - F[l][L[v] - 1];
    					else sumB += F[l][R[v]] - F[l][M[v]];
    				}
    			}
    			sumA = F[l][n] - sumB;
    			f[u][s << (N + 1 - d) | 1] = sumA + sta[l] * C[l];
    			f[u][s << (N + 1 - d)] = sumB + (!sta[l]) * C[l];
    			//if (sumA < 0 || sumB < 0) puts("LXT");
    		}
    		return;
    	}
    	int mid = l + r >> 1;
    	L[u] = l; R[u] = r; M[u] = mid;
    	dfs(ls,l,mid,d + 1);
    	dfs(rs,mid + 1,r,d + 1);
    	int maxv = (1 << d) - 1,b = N + 1 - d;
    	for (int s = 0; s <= maxv; s++){
    		for (int Al = 0; Al <= (mid - l + 1); Al++)
    			for (int Ar = 0; Ar <= (r - mid); Ar++){
    				if (Al + Ar < (r - l + 1) - Al - Ar){
    					int e = (s << b),t = (s << b) + Al + Ar;
    					f[u][t] = min(f[u][t],f[ls][e + Al] + f[rs][e + Ar]);
    				}
    				else {
    					int e = ((s << 1 | 1) << b - 1),t = (s << b) + Al + Ar;
    					f[u][t] = min(f[u][t],f[ls][e + Al] + f[rs][e + Ar]);
    				}
    			}
    	}
    }
    int main(){
    	memset(f,0x3f3f3f3f,sizeof(f));
    	N = read(); n = 1 << N;
    	REP(i,n) sta[i] = read();
    	REP(i,n) C[i] = read();
    	REP(i,n) for (int j = i + 1; j <= n; j++) F[i][j] = F[j][i] = read();
    	REP(i,n) for (int j = 1; j <= n; j++) F[i][j] += F[i][j - 1];
    	dfs(1,1,n,0);
    	int ans = 0x3f3f3f3f,maxv = (1 << N + 1) - 1;
    	for (int i = 0; i <= maxv; i++) ans = min(ans,f[1][i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Android 适配知识点
    Android Studio各种快捷功能及好用的插件
    81.Android之沉浸式状态栏攻略
    8.Android 系统状态栏沉浸式/透明化解决方案
    为开发者准备的 Android 函数库(2016 年版)
    GitHub 上 57 款最流行的开源深度学习项目
    7.Android开源项目WheelView的时间和地址联动选择对话框
    6.初探Asynctask
    5.Android消息推送机制简单例子
    让你Android开发更简单
  • 原文地址:https://www.cnblogs.com/Mychael/p/9227389.html
Copyright © 2011-2022 走看看