题目: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;
}