151 条题解
-
8
PowderHan LV 10 @ 7 年前
-
27 年前@
最基础的树形dp
根据从属关系建立二叉树,左孩子右兄弟(详见代码)
再从根节点记忆化搜索即可 -
17 年前@
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int n,m;
int l[302],r[302],last[302];
int val[302];
int max(int a,int b)
{
return a>b?a:b;
}
void build(int x,int y)
{
if(l[y]==-1) l[y]=x;
else r[last[y]]=x;
last[y]=x;
}
int f[302][302];// f[i][j] : 以 i 为根的子树中 选j门课 最多学分
int ans=0;
int work(int pos,int k)
{
if(pos<0||k<=0) return 0;
if(f[pos][k]!=-1) return f[pos][k];
f[pos][k]=work(r[pos],k);
for(int i=0;i<=k-1;i++)
{
f[pos][k]=max(f[pos][k],work(l[pos],i)+work(r[pos],k-i-1)+val[pos]);
}
return f[pos][k];
}
int main()
{
int i,j;
memset(l,-1,sizeof(l));
memset(f,-1,sizeof(f));
memset(r,-1,sizeof(r));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
int x;
scanf("%d%d",&x,&val[i]);
build(i,x);//i 的 父亲是 x
}
printf("%d",work(0,m+1));
return 0;
} -
17 年前@
树形dp秒杀
-
17 年前@
-
03 年前@
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100;
int n,m;
int y;
int d = 1;
void DP(int u);
vector <int> tree[MAXN];
int f[MAXN][MAXN];//节点i之后选了j门课的最大学分值。
int a[MAXN/10][MAXN/10]; // 存储元素
void init(){
scanf("%d %d", &n, &m); //n为共有n门课程,需要选择m门课程
for(int i=1;i<=n;++i){
//f[i][1]代表的就是以当前节点为根节点只选择一门课的学分,也就是该门课本身的学分,即v[i]
scanf("%d %d",&y,&f[i][1]);
tree[y].push_back(i);
}
DP(0);
}
/**
* 实现DP问题,为了有统一的根节点,设置原始结点为0,即所有课程根节点都是课程为0的
* 所以下面的实现过程中,最终的学分最大为f[0][m+1]
* @param u
*/
void DP(int u){
for (int i = 0; i < tree[u].size(); ++i) {
int son = tree[u][i];//节点u的子节点
printf("%d\n", son);
DP(son);
for (int j = m + 1; j >= 1; --j) {
for (int k = 0; k < j; ++k) {
f[u][j] = max(f[u][j], f[son][k] + f[u][j - k]);}
}
}
}
int main(){
init();
printf("%d",f[0][m+1]);
return 0;
} -
06 年前@
-
07 年前@
n只有300,搞一个不递归的写法过掉。
-
07 年前@
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define N 1000+10using namespace std;
struct Node{
int left;
int right;
int data;
}a[N];
int f[N][N],child[N];
int n,q;
bool root[N];
//记忆化搜索
int dfs(int x,int num)
{
if (f[x][num])return f[x][num];
if (num==0||x==0)return 0;
f[x][num]=dfs(a[x].right,num);
for (int k=0;k<=num-1;++k)
{
f[x][num]=max(f[x][num],dfs(a[x].left,k)+dfs(a[x].right,num-1-k)+a[x].data);
}
return f[x][num];
}int main(void)
{
scanf("%d%d",&n,&q);
for (int i=1;i<=n;++i)
{
int s,d;
scanf("%d%d",&s,&d);
a[i].right=a[s].left;
a[s].left=i;
a[i].data=d;
}
printf("%d",dfs(a[0].left,q));
return 0;
} -
015 年前@
发现用C做的好像挺少的,贴下...
#includeusing namespace std;
const int N = 305;
int isLeaf[N], Leaf[N];
int fath[N];
int DP[N][N];
int Q[N];void Dp(int p1, int p2, int c) {
for(int i = c; i >= 2; i --) {
for(int j = i - 1; j > 0; j --) {
DP[p2][i] = max(DP[p2][i], DP[p2][i - j] + DP[p1][j]);
}
}
}int main() {
int n, m, front = 0, back = 0, buf, f;
scanf("%d%d", &n, &m);
m ++;
for(int i = 1; i -
015 年前@
var
f:array[0..300,0..300]of integer;
left,right,w:array[0..300]of integer;
n,m,i,dad,j:integer;function dp(p,k:integer):integer;
var
i,temp,max:integer;
begin
if f[p,k]-1 then exit(f[p,k]);
if (p=0) then exit(0); {it means it's the end of a tree}
max:=0;
for i:=0 to (k-1) do begin
temp:=dp(left[p],i)+dp(right[p],k-i-1)+w[p];
if temp>max then max:=temp;
end;
temp:=dp(right[p],k);
if temp>max then max:=temp;
f[p,k]:=max;
exit(max);
end;begin
readln(n,m);
fillchar(f,sizeof(f),255);
for i:=1 to n do begin
readln(dad,w[i]);
right[i]:=left[dad];
left[dad]:=i;
f:=0;
end;
writeln(dp(left[0],m));end.
一点小错误 w[i]... 导致悲剧了两个小时。。。。以后发现不行 立刻重写!!!!
-
015 年前@
program vijos_1180;
type
tree=record
l,r:longint;
end;
var
w,fg:array[1..300]of longint;
a:array[0..300]of tree;
f:array[0..30,0..30]of longint;
n,m,i,j,k:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a)
else exit(b);
end;
procedure work(i,j:longint);
var
k:longint;
begin
if f>=0 then exit;
work(a[i].r,j);
f:=f[a[i].r,j];
for k:=0 to j-1 do
if (j-k-1>=0)and(j-k-1 -
015 年前@
var
n,m,i,j,x:longint;
right,left,w:array[0..2000]of longint;
f:array[0..1000,0..500]of longint;
t:array[0..1000,0..500]of boolean;
procedure addbrother(brother,son:longint);
begin
if right[brother]=0 then right[brother]:=son
else addbrother(right[brother],son);
end;
procedure addson(father,son:longint);
begin
if left[father]=0 then left[father]:=son
else addbrother(left[father],son);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure doit(now,j:longint);
var k:longint;
begin
if (j=0)or (now=0) then exit;
if not(t[right[now],j]) then doit(right[now],j);
f[now,j]:=f[right[now],j];
for k:=0 to j-1 do
begin
if not(t[left[now],k]) then doit(left[now],k);
if not(t[right[now],j-k-1]) then doit(right[now],j-k-1);
f[now,j]:=max(f[now,j],f[left[now],k]+f[right[now],j-k-1]+w[now]);
end;
t[now,j]:=true;
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(x,w[i]);
addson(x,i);
end;
for i:=0 to m do t[0,i]:=true;
for i:=1 to n do
for j:=1 to m do doit(i,j);
writeln(f[left[0],m]);
end. -
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms小庆一下60题~~~
-
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 9ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:9ms
program p1180;
var n,m,dad,root:longint;
right,left,cost:array[0..1000]of longint;
f:array[0..1000,0..1000]of longint;
procedure init;
var i:longint;
begin
readln(n,m);
for i:=1 to n do
begin
readln(dad,cost[i]);
right[i]:=left[dad];
left[dad]:=i;
if dad=0 then root:=i;
end;
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x);exit(y);
end;
procedure treedp(k,l:longint);
var i:longint;
begin
if (l=0)or(k=0) then exit;
if f[k,l]>0 then exit;
treedp(right[k],l);
f[k,l]:=f[right[k],l];
for i:=0 to l-1 do
begin
treedp(left[k],i);
treedp(right[k],l-i-1);
f[k,l]:=max(f[k,l],f[left[k],i]+f[right[k],l-i-1]+cost[k]);
end;
end;
begin
init;
fillchar(f,sizeof(f),0);
treedp(root,m);
writeln(f[root,m]);
end. -
015 年前@
注意了。。转二叉树后,根节点0和孩子没有从属关系。。。
-
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0ms多叉转二叉
-
015 年前@
编译通过...
├ 测试数据 01:答案正确... 0ms
├ 测试数据 02:答案正确... 0ms
├ 测试数据 03:答案正确... 0ms
├ 测试数据 04:答案正确... 0ms
├ 测试数据 05:答案正确... 0ms
---|---|---|---|---|---|---|---|-
Accepted 有效得分:100 有效耗时:0msdp程序就是短啊就是短~~
感谢lx Cambridge 神牛的方程提醒。。
给段核心的
if x=0 then exit;
if f[x,y]>0 then exit;
if y=0 then
begin
f[x,y]:=0;
exit;
end;
if tree[x][1]0 then
begin
treedp(tree[x][1],y);
f[x,y]:=f[tree[x][1],y];
end;
for i := 0 to y-1 do
begin
treedp(tree[x][0],i);
treedp(tree[x][1],y-i-1);
if f[tree[x][0],i]+score[x]+f[tree[x][1],y-i-1]>f[x,y]
then f[x,y]:=f[tree[x][0],i]+score[x]+f[tree[x][1],y-i-1];
end; -
015 年前@
不用转二叉也能秒
-
015 年前@
水题