洛谷:P2014 [CTSC1997]选课

深搜 背包 dp

题目:

在这里插入图片描述

分析:本来想着对每一棵二叉树进行操作,看题解,加一个点就把森林变成了一颗标准的二叉树。

确实有点背包的意思,其实我也想到背包问题了,可是无从下手。

三维的我会。看题解,有意思:

在这里插入图片描述

错误代码:背包类似问题怎么能用递归呢?仔细分析分析,以下代码的dp运行过程基本全错。真的这样吗?

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > vv;
int m,n;//n 要选的数量 
int B[305];
int A[305][305];
int f(int x,int y)
{
 if(A[x][y]!=-1) return A[x][y];
 if(y==0) return 0;
 if(y==1) 
 {
  A[x][y]=B[x];
  return B[x];
 }
 if(vv[x].size()==0){
  A[x][y]=B[x];
  return B[x];
 }
 if(vv[x].size()==1)
 {
  A[x][y]=f(vv[x][0],y-1)+B[x];
  return A[x][y];
 }
 A[x][y]=f(vv[x][0],y-1)+B[x];
 for(int k=1;k<vv[x].size();k++)
 for(int i=1;i<y;i++)
 {
  A[x][y]=max(A[x][y],f(x,y-i)+f(vv[x][k],i));
 }
 return A[x][y];
}
int main()
{
 cin>>m>>n;
 memset(B,0,sizeof(B));
 memset(A,-1,sizeof(A));
 vector<int> v;
 for(int i=0;i<=m;i++) vv.push_back(v);
 for(int i=1;i<=m;i++)
 {
  int a;
  cin>>a>>B[i];
  vv[a].push_back(i);
 }
 cout<<f(0,n+1);
}

代码:妈的,哪里又错了,感觉逻辑没有问题:

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > vv;
int m,n;//n 要选的数量 
int B[305];
int A[305][305];
int f(int x)
{
 A[x][1]=B[x];
 int to;
    for(int k = 0; k<vv[x].size(); k++) { // 遍历 x 的所有子节点
        to = vv[x][k]; // to 是 x 的一个子节点
        f(to); // 计算 to 节点的 f 数组
        for (int j = m; j >= 1; j--)//倒序枚举,使用 to 节点的 f 数组更新 x 节点的 f 数组
            for (int i = j - 1; i >= 1; i--)
                A[x][j] = max(A[x][j], A[x][j - i] + A[to][i]);
    }
}
int main()
{
 cin>>m>>n;
 memset(B,0,sizeof(B));
 memset(A,-1,sizeof(A));
 vector<int> v;
 for(int i=0;i<=m;i++) vv.push_back(v);
 for(int i=1;i<=m;i++)
 {
  int a;
  cin>>a>>B[i];
  vv[a].push_back(i);
 }
 //A[x][y]=max(A[x][y],f(x,y-i)+f(vv[x][k],i));
 f(0);
 cout<<A[0][m];
}

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/107746932