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++;
	}
}
posted @ 2022-04-03 12:58  Burnling  阅读(21)  评论(0编辑  收藏  举报