220403总结
220403总结
被挂在树上的一天(生活在树上.doc
多重背包二进制拆分的时候还写错了个变量
T1 求后序遍历
- 先序遍历:中 — 左 — 右
- 中序遍历:左 — 中 — 右
- 后序遍历:左 — 右 — 中
求后序遍历的基本方法就是,通过先序遍历求出子树的根,再通过中序遍历确定左子树和右子树
没有必要建树
并且由于给出了先序遍历,以 \(i\) 为根的子树的根就是先序遍历的第 \(i\) 项
//l1,r1为该树在先序遍历中的位置
//l2,r2为该树在中序遍历中的位置
void build(int l1,int r1,int l2,int r2){
int rt = strchr(B,A[l1]) - B;//找子树的根在中序遍历的位置
//左子树长度为rt-l2,右子树长度为r2-rt
// 若 rt-l2 > 0,即 rt > l2 时,有左子树
// 若 r2-rt > 0,即 rt < r2 时,有右子树
//在先序遍历中,
// [l1+1,l1+(rt-l2)]为左子树区间
// [l1+(rt-l2)+1,r2]为右子树区间
//在中序遍历中,[l2,rt-1]即为左子树区间,[rt+1,r2]为右子树区间
//顺便进行后序遍历(左 — 右 — 根)
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背包即可
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 扩展二叉树
做的时候没考虑到可能只补了一个点的情况
扩展二叉树的序列中一个点要么是补点,要么是树上的点
树上的点的后一个点为其左子树的根,左子树中最后一个点的下一个点为右子树的根
递归求解即可
struct Tree{
int ls,rs;
char c;
}tree[100000];
char T[100000];
//ind需要放在递归外面,因为它需要不断向后跑
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++;
}
}