树形DP&&分组背包练习题目

背包:

#include<cstdio>
#include<vector>
#define mp make_pair
using namespace std;
typedef pair<int,int> pii;
inline int max(int x,int y)
{
return x>y?x:y;
}
inline int min(int x,int y)
{
return x<y?x:y;
}
const int N=2200;
vector < pair <int,int> > t[N];
int f[N],n,m,T;
int main()
{
int a,b,c;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
t[c].push_back(mp(b,a));
}
for(int i=1;i<=100;i++)
for(int v=m;v>=0;v--)
{
for(int j=0;j<t[i].size();j++)
{
int w=t[i][j].second,val=t[i][j].first;
if(v>=w)
f[v]=max(f[v],f[v-w]+val);
}
}
printf("%d",f[m]);
return 0;
}

二叉苹果树:

/*
思路:树形DP+背包!
考虑设f[i][j]表示以i为根节点的子树,保留j个数值所拥有的最大苹果树
有方程f[i][j]=max(f[i][j],f[i][k]+f[v][j-k-1]+e[i].w);
其中 1<=j<=min(m,size[i]);
0<=k<=min(j-1,size[v])
首先,为了保证当前节点上的苹果产生贡献,必须把它与子节点相连,所以就是总和
k-1!
代码一:直接存树,做树上DP
*/
#include<cstdio>
using namespace std;
const int N=120;
int f[N][N];
struct node{
int from;
int to;
int val;
int next;
}e[N<<1];
int head[N],num,n,m,size[N];
inline int min(int x,int y)
{
return x<y?x:y;
}
inline int max(int x,int y)
{
return x>y?x:y;
}
void addedge(int from,int to,int w)
{
e[++num].from=from;
e[num].to=to;
e[num].next=head[from];
e[num].val=w;
head[from]=num;
}
void dp(int u,int fa)
{
size[u]=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to,w=e[i].val;
if(v==fa)
continue;
dp(v,u);
size[u]+=size[v];
for(int j=min(m,size[u]);j;j--)
{
for(int k=min(size[v],j-1);k>=0;k--)
f[u][j]=max(f[u][j],f[u][j-k-1]+f[v][k]+w);
}
}
}
int main()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
dp(1,-1);
printf("%d",f[1][m]);
return 0;
}

2.

/*
方法二:建一颗二叉树,做左右儿子上的DP
重点:建树方法+记忆化搜索
还有将边权转化为儿子节点上的点
*/

#include<cstdio>
using namespace std;
const int N=120;
int map[N][N],ls[N],rs[N],n,m,f[N][N],a[N];
inline int max(int x,int y)
{
return x>y?x:y;
}
void maketree(int u)
{
for(int i=1;i<=n;i++)
{
if(map[u][i]>=0)
{
a[i]=map[u][i];
map[u][i]=-1;
map[i][u]=-1;
ls[u]=i;
maketree(ls[u]);
break;
}
}
for(int i=1;i<=n;i++)
{
if(map[u][i]>=0)
{
a[i]=map[u][i];
map[u][i]=-1;
map[i][u]=-1;
rs[u]=i;
maketree(rs[u]);
break;
}
}
}
int DP(int x,int y) //x root y branches
{
if(y==0)
return 0;
if(ls[x]==0&&rs[x]==0)
return a[x];
if(f[x][y]>0)
return f[x][y];
for(int i=0;i<=y-1;i++)
f[x][y]=max(f[x][y],DP(ls[x],i)+DP(rs[x],y-i-1)+a[x]);
return f[x][y];
}
int main()
{
int x,y,z;
scanf("%d%d",&n,&m);
m++;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=-1;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
map[x][y]=z;
map[y][x]=z;
}
maketree(1);
printf("%d",DP(1,m));
return 0;
}

猜你喜欢

转载自www.cnblogs.com/little-cute-hjr/p/11814364.html