树形DP 洛谷P1490 奶思
第一个代码 很巧妙
数据是 dfs 过后的数据 因为本来dfs就是一种递归
那么就可以去递归的重新读数据
重新 递归 dfs 但是时间效率不是很高
记忆化搜索
//MADE BY Y_is_sunshine;
//#include <bits/stdc++.h>
//#include <memory.h>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <math.h>
#define INF 0x3f3f3f3f
#define MAXN 1005
const int mod = 1e9 + 7;
using namespace std;
struct node {
int to;
int next;
}edge[MAXN << 1];
int N, M;
int cnt_1 = 0;
int cost[MAXN * 10];
int price[MAXN * 10];
int dp[MAXN][MAXN];
void read(int x) {
cin >> cost[x] >> price[x];
cost[x] *= 2;
if (!price[x])
read(x << 1), read(x << 1 | 1);
}
int dfs(int u, int time) {
if (dp[u][time] || !time)
return dp[u][time];
if (price[u])
return dp[u][time] = min(price[u], (time - cost[u]) / 5);
for (int k = 0; k <= time - cost[u]; k++)
dp[u][time] = max(dp[u][time], dfs(u << 1, k) + dfs(u << 1 | 1, time - cost[u] - k)); // 二分
return dp[u][time];
}
int main()
{
freopen("data.txt", "r", stdin);
cin >> N;
read(1);
cout << dfs(1, N - 1) << endl;
freopen("CON", "r", stdin);
system("pause");
return 0;
}
另附 第二个时间效率更高的代码
巨佬的 代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1001
using namespace std;
int n,cnt,tot;
int f[maxn][maxn];
void dfs()
{
int root=++cnt,limit,time;
scanf("%d%d",&limit,&tot);
limit<<=1;
if(tot)//子节点
{
for(int time=limit;time<=n;time++)
f[root][time]=min((time-limit)/5,tot);//判断取多少
}
else
{
int left=cnt+1,right;dfs();
right=cnt+1;dfs();
for(int time=limit;time<=n;time++)
for(int lctime=0;lctime<=time-limit;lctime++)//分配给左树的时间
{
f[root][time]=max(f[root][time],f[left][lctime]+f[right][time-limit-lctime]);//左右子树的和
}
}
}
int main()
{
scanf("%d",&n);n--;
dfs();
printf("%d\n",f[1][n]);
return 0;
}