原题链接:https://www.luogu.org/problemnew/show/P3360
题目大意
给一个有根树,有边权,叶子节点有画可以偷,偷画和经过边需要时间,给定n时间,最多可以偷多少价值的画。
解法
这奇怪的数据格式真是给跪了,叶子节点可以背包,非叶子节点怎么办呢?暴力枚举!
#include <iostream>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define pb push_back
using namespace std;
typedef long long LL;
const int N=1000+5;
struct Node{
int lchild,rchild,w,x;
}Tree[N];
int cnt=0;
int New(int w,int x){
Tree[++cnt].w=w;
Tree[cnt].x=x;
Tree[cnt].lchild=-1;
Tree[cnt].rchild=-1;
return cnt;
}
int dp[300+5][30+5][600+5];
int Build(){
int t,x,w,c;
cin>>t>>x;
int r=New(t,x);
if(x>0){
//dp[300][30][600]
// cout<<"r is "<<r<<endl;
for(int i=1;i<=x;i++){
cin>>w>>c;
for(int j=1;j<=600;j++){
if(j>=c) dp[r][i][j]=max(dp[r][i-1][j],dp[r][i-1][j-c]+w);
else dp[r][i][j]=dp[r][i-1][j];
// cout<<dp[r][i][j]<<" ";
}
// cout<<endl;
}
// cout<<endl;
}
else if(x==0){
Tree[r].lchild=Build();
Tree[r].rchild=Build();
}
return r;
}
void dfs(int u){
if(Tree[u].x>0) return ;
int l=Tree[u].lchild;
int r=Tree[u].rchild;
dfs(l);
dfs(r);
int lx=(Tree[l].x>0?Tree[l].x:2);
int rx=(Tree[r].x>0?Tree[r].x:2);
int lw=Tree[l].w;
int rw=Tree[r].w;
for(int i=0;i<=600;i++){
for(int j=0;j+i<=600;j++){
dp[u][2][i+j]=max(dp[u][2][i+j],(i-2*lw>=0?dp[l][lx][i-2*lw]:0)+(j-2*rw>=0?dp[r][rx][j-2*rw]:0));
}
}
}
int main() {
#ifdef LOCAL_DEFINE
freopen("input.in", "rt", stdin);
#endif
int n;
cin>>n;
int r=Build();
dfs(r);
int rw=Tree[r].w;
cout<<dp[r][2][n-2*rw-1]<<endl;
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}