树形dp-访问美术馆

主要问题: 树如何编号(重点:如何体现父子关系)

树的编号方式:

1)读入给了编号并给予父子关系 (父子关系已给出) 处理:同存图

2)将数组转化为一个树 父子关系体现在其编号上(编号的关系->父子关系)典型:线段树,堆(lson:2*x rson: 2*x+1)

void dfs(int x)
{
	cin>>a[x].x>>a[x].w;
	a[x].x*=2;
	if(a[x].w==0)
	{
		dfs(x*2);dfs(x*2+1);
	}
}

3)直接搞dfs序,一边深搜一边编号

void find()
{
	cnt++;int x=cnt;
	int a,b;cin>>a>>b;
	if(b==0)
	{
		int l=cnt+1,r;find();
		r=cnt+1;find();
		v[x].push_back(l);v[x].push_back(r);
	}
}

Then是完整代码

方法1:dfs序

由于输入的访问次序与dfs序相同,所以直接做一遍dfs找出lson,rson即可,无需额外存储父子关系

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;
const int maxn=1005;
vector<int> v[maxn];
int f[maxn][maxn];
int cnt=0;
int n;
void find()
{
	cnt++;int x=cnt;
	int w,val;cin>>w>>val;
	w*=2;
	if(val==0)
	{
		int l=cnt+1,r;find();
		r=cnt+1;find();
		for(int tim=w;tim<=n;tim++)
		{
			for(int p=0;p<=tim-w;p++)
			{
				int temp=f[l][p]+f[r][tim-w-p];
				f[x][tim]=max(f[x][tim],temp);	
			}
		}
	}
	else
	{
		for(int tim=w;tim<=n;tim++)
		{
			f[cnt][tim]=min(val,(tim-w)/5); 
		} 
	}
}
int main()
{
	cin>>n;n--; 
	find();
	cout<<f[1][n]<<endl;
	return 0;
}

方法2:采用线段树的存储方法(lson=2*x,rson=2*x+1)

此方法可能存在空结点,没有完全利用。

#include <iostream>
#include <cstdio>
#include <vector>
 
using namespace std;

const int maxn=1005;
struct node
{
	int x;int w;
}a[maxn];
int f[maxn][maxn];
int cnt;node k;
void dfs(int x)
{
	cin>>a[x].x>>a[x].w;
	a[x].x*=2;
	if(a[x].w==0)
	{
		dfs(x*2);dfs(x*2+1);
	}
}
int find(int x,int cost)
{
	if(cost==0||f[x][cost]) return f[x][cost];
	if(a[x].w) return f[x][cost]=min(a[x].w,(cost-a[x].x)/5);
	for(int p=0;p<=cost-a[x].x;p++)
	{
		int temp=find(x*2,p)+find(x*2+1,cost-p-a[x].x);
		f[x][cost]=max(f[x][cost],temp);
	}
	return f[x][cost];
}
int main()
{
	int t;scanf("%d",&t);t-=1;
	dfs(1);
	cnt=0;
	cout<<find(1,t)<<endl;
	return 0;
 } 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章