被挂在树上的一天(生活在树上.doc
多重背包二进制拆分的时候还写错了个变量
T1 求后序遍历
- 先序遍历:中 — 左 — 右
- 中序遍历:左 — 中 — 右
- 后序遍历:左 — 右 — 中
求后序遍历的基本方法就是,通过先序遍历求出子树的根,再通过中序遍历确定左子树和右子树
没有必要建树
并且由于给出了先序遍历,以 $i$ 为根的子树的根就是先序遍历的第 $i$ 项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
void build(int l1,int r1,int l2,int r2){ int rt = strchr(B,A[l1]) - B; if(rt > l2) build(l1+1,l1+rt-l2,l2,rt-1); if(rt < r2) build(l1+rt-l2+1,r1,rt+1,r2); printf("%c",A[l1]); }
|
T2 混合背包
确实是混合背包(指同时出现01背包,多重背包,完全背包)
01背包是个数为1的多重背包
完全背包是个数为正无穷的多重背包
所以三个背包都可以转化为多重背包求解
由于物品的重量为正整数,背包容量上限为200,
所以其实把完全背包看成物品个数为250的多重背包就完全足够了…吧
考虑到没有给出 $w,c,p$ 的数据范围,
对完全背包物品数量进行了二进制拆分
拆分的时候把一个p写成了w丢了60分
再跑一遍01背包即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| int V,N; int dp[100000]; int va[100000]; int we[100000];
scanf("%d%d",&V,&N); memset(va,0,sizeof(va)); memset(we,0,sizeof(we)); for(int i = 1; i<=N; i++) { int w,c,p; scanf("%d%d%d",&w,&c,&p); if(!p) p = 250; for(int j = 1;j<=p;j<<=1){ cnt++; va[cnt] = c * j; we[cnt] = w * j; p -= j; } if(p){ cnt++; va[cnt] = c * p; we[cnt] = w * p; } } for(int i = 1;i<=cnt;i++){ for(int j = V;j>=we[i];j--){ dp[j] = max(dp[j],dp[j-we[i]]+va[i]); } } printf("%d\n",dp[V]);
|
T3 扩展二叉树
做的时候没考虑到可能只补了一个点的情况
扩展二叉树的序列中一个点要么是补点,要么是树上的点
树上的点的后一个点为其左子树的根,左子树中最后一个点的下一个点为右子树的根
递归求解即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| struct Tree{ int ls,rs; char c; }tree[100000];
char T[100000];
int ind = 0;
void build(){ int rt = ind; if(T[ind+1]!='.'){ tree[rt].ls = ind+1; ind++;build(); }else{ ind++; } if(T[ind+1]!='.'){ tree[rt].rs = ind+1; ind++;build(); }else{ ind++; } }
|