BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】
2018-06-26 09:04
429 查看
题目链接
题解
观察表格,实际上就是分\(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] - 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\n",ans); return 0; }
相关文章推荐
- bzoj1495 [NOI2006] 网络收费 树形DP
- bzoj1495 [NOI2006]网络收费(状压/暴力+树形dp)
- BZOJ_1495_[NOI2006]网络收费_树形DP
- 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp
- 【BZOJ1495】[NOI2006]网络收费 暴力+DP
- Bzoj1495: [NOI2006]网络收费
- [BZOJ1495][NOI2006]网络收费
- Bzoj1495: [NOI2006]网络收费
- bzoj 1495: [NOI2006]网络收费
- bzoj 1564 [NOI2009]二叉查找树(树形DP)
- [环套树 树形DP 期望] BZOJ 2878 [Noi2012]迷失游乐园
- [BZOJ1564][NOI2009]二叉查找树 树形dp 区间dp
- 【BZOJ 2878】 2878: [Noi2012]迷失游乐园 (环套树、树形概率DP)
- [BZOJ1596][Usaco2008 Jan]电话网络(树形dp)
- NOI2006 网络收费 network
- [容斥 状压DP 树形DP] BZOJ 4455 [Zjoi2016]小星星 & UOJ #185 【ZJOI2016】小星星
- BZOJ 1063: [Noi2008]道路设计 树形DP
- BZOJ1509_NOI 2003_逃学的小孩 两次遍历 树形DP
- BZOJ2878 [Noi2012]迷失游乐园 【基环树 + 树形dp + 期望dp】
- BZOJ2435 [Noi2011]道路修建 【树形Dp 吧。。】