gfoj 寻宝

题目:gfoj---course---动态规划2---寻宝

一道经典的树形dp题目!!!

状态转移方程:

for (j=m;j>=0;j--)		//j:天数 必须倒着循环
	for (k=0;k<=j-2*n1.t;k++)
		f[x][j]=max(f[x][j],f[x][j-2*n1.t-k]+f[n1.y][k]);

此f[x,j]指:从x开始走j天(必须走回x!!!)获得宝藏的最大值 !!!

若没有符合j的走法,则 =0 

意义:!!!

当搜到第 i个孩子时,前 i-1个孩子的搜索数据都更新到父亲节点,所以才会有  f[x][j-2*n1.t-k]+f[n1.y][k]

f[x][j-2*n1.t-k]:前 i-1个孩子走j-2*n1.t-k天获得宝藏的最大值

f[n1.y][k]:第 i个孩子走k天获得宝藏的最大值


ps:当没有终止条件时用EOF:

while (scanf("%d",&n)!=EOF)
{

}

更详细解析:https://user.qzone.qq.com/50222268/blog/1534322227

程序:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

struct node
{
	int t, y;
};

const int maxSize=100;
vector <node> N[maxSize+5];
int vis[maxSize+5],f[maxSize+5][maxSize+5],a[maxSize+5];
int m,k,n;

void dfs(int x)
{
	int i,j,k;
	node n1;
	
	f[x][0]=a[x];
	for (i=0;i<N[x].size();i++)
	{
		n1=N[x][i];
		if (vis[n1.y]==1)
			continue;
		vis[n1.y]=1;
		dfs(n1.y);
		vis[n1.y]=0;
		for (j=m;j>=0;j--)		//j:天数 必须倒着循环
			for (k=0;k<=j-2*n1.t;k++)
				f[x][j]=max(f[x][j],f[x][j-2*n1.t-k]+f[n1.y][k]);
		//f[x,j]:从x开始走j天(必须走回x!!!)获得的最大值 
		//若没有符合j的走法,则 =0 
	}
}

int main()
{
	int i,x,y,z,ans;
	node n1;
	
	freopen("a.txt","r",stdin);
	while (scanf("%d",&n)!=EOF)//!!!!!!!!!!!!!!!!
	{
		memset(vis,0,sizeof(vis));
		memset(f,0,sizeof(f));
		memset(a,0,sizeof(a));
		for (i=1;i<=n;i++)
			N[i].clear();
		
		for (i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for (i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			n1.y=y;	n1.t=z;
			N[x].push_back(n1);
			n1.y=x;
			N[y].push_back(n1);
		}
		scanf("%d%d",&k,&m);
		
		vis[k]=1;
		dfs(k);
		ans=0;
		for (i=0;i<=m;i++)
			ans=max(ans,f[k][i]);
		printf("%d\n",ans);
	}
	
	
	
	return 0;
}

类似题目:http://acm.hdu.edu.cn/showproblem.php?pid=1561

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

struct node
{
	int wei,y;
};

const int maxSize=200;
int n,m;
int vis[maxSize+5],f[maxSize+5][maxSize+5];
vector <node> N[maxSize+5];

void dfs(int x)
{
	int i,j,k;
	node n1;
	
	for (i=0;i<N[x].size();i++)
	{
		n1=N[x][i];
		if (vis[n1.y]==1)
			continue;
		vis[n1.y]=1;
		f[n1.y][1]=n1.wei;
		dfs(n1.y);
		vis[n1.y]=0;
		if (x!=0)
			for (j=m;j>0;j--)
				for (k=0;k<j;k++)
					f[x][j]=max(f[x][j],f[x][j-k]+f[n1.y][k]);
		else
			for (j=m;j>=0;j--)
				for (k=0;k<=j;k++)
					f[x][j]=max(f[x][j],f[x][j-k]+f[n1.y][k]);		
	}
}


int main()
{
	int i,x,y,ans;
	node n1;
	
	freopen("a.txt","r",stdin);
	while (1)
	{
		memset(f,0,sizeof(f));
		memset(vis,0,sizeof(vis));
		for (i=0;i<=n;i++)
			N[i].clear();
			
		scanf("%d%d",&n,&m);
		if (n==0 && m==0)
			break;		
		for (i=1;i<=n;i++)
		{
			scanf("%d%d",&x,&y);
			n1.y=i;	n1.wei=y;
			N[x].push_back(n1);
		}
		
		vis[0]=1;
		dfs(0);
		ans=0;
		for (i=1;i<=m;i++)
			ans=max(ans,f[0][i]);
		printf("%d\n",ans);
	}
	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/scutbenson/article/details/81738322