http://acm.hdu.edu.cn/showproblem.php?pid=4616

要记录各种状态的段  a[2][4]

a[0][j]表示以trap为起点一共有j个trap的最优值

a[1][j]表示不以trap为起点一共有j个trap的最优值

dp[x][i][j] 表示以x为根节点的子树从各个叶子到x节点的各状态最优值

每到一个节点 要枚举经过此节点的所有符合要求的段中最优的(需要合并段)

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<algorithm>
#include<queue>
#include<bitset>
#include<deque>
#include<numeric> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll;
typedef unsigned int uint;
typedef pair<int,int> pp;
const double eps=1e-9;
const int INF=0x3f3f3f3f;
const ll MOD=1000000007;
const int N=100005;
int head[N],I;
struct node
{
int j,next;
}edge[N*2];
int value[N],trap[N];
int dp[N][2][4];
int ans,C;
void add(int i,int j)
{
edge[I].j=j;
edge[I].next=head[i];
head[i]=I++;
}
void init(int n)
{
for(int i=0;i<n;++i)
scanf("%d %d",&value[i],&trap[i]);
memset(head,-1,sizeof(head));I=0;
for(int i=1;i<n;++i)
{
int l,r;
scanf("%d %d",&l,&r);
add(l,r);
add(r,l);
}
}
void copyArr(int (*b)[4],int (*a)[4])
{
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
b[i][j]=a[i][j];
}
void clArr(int (*b)[4])
{
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
b[i][j]=-1;
b[0][0]=b[1][0]=0;
}
void update(int (*b)[4],int x)
{
if(trap[x]==0)
{
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
if(b[i][j]!=-1)
b[i][j]+=value[x];
b[0][0]=0;
}else
{
for(int i=0;i<2;++i)
for(int j=3;j>0;--j)
{
if(b[i][j-1]!=-1)
b[i][j]=b[i][j-1]+value[x];
}
b[0][0]=0;
b[1][0]=0;
}
}
void print(int (*b)[4])
{
for(int i=0;i<2;++i)
{
for(int j=0;j<4;++j)
printf("%4d ",b[i][j]);printf("\n");
}printf("\n");
}
void findAns(int (*b)[4],int (*v1)[4],int (*v2)[4],int x)
{
int c=C-trap[x];
int tmp=0;
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
{
for(int l=0;l<2;++l)
for(int r=0;r<4;++r)
{
if(j+r>c) continue;
if(j+r==c)
{
if(i+l==2) continue;
if(i!=l)
{
if(i==0&&j==0) continue;
if(l==0&&r==0) continue;
}
}
if(v1[l][r]!=b[l][r])
tmp=max(tmp,max(0,v1[l][r])+max(0,b[i][j]));
else
tmp=max(tmp,max(0,v2[l][r])+max(0,b[i][j]));
}
}
ans=max(ans,tmp+value[x]);
}
void dfs(int pre,int x,int (*a)[4])
{
int b[2][4];
copyArr(b,a);
update(b,x);
int v1[2][4],v2[2][4];
clArr(v1);clArr(v2);
for(int t=head[x];t!=-1;t=edge[t].next)
{
int l=edge[t].j;
if(l==pre) continue;
dfs(x,l,b);
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
{
v2[i][j]=max(v2[i][j],dp[l][i][j]);
if(v1[i][j]<v2[i][j])
swap(v1[i][j],v2[i][j]);
}
}
copyArr(dp[x],v1);
update(dp[x],x);
for(int i=0;i<2;++i)
for(int j=0;j<4;++j)
{
v2[i][j]=max(v2[i][j],a[i][j]);
if(v1[i][j]<v2[i][j])
swap(v1[i][j],v2[i][j]);
}
findAns(a,v1,v2,x);
for(int t=head[x];t!=-1;t=edge[t].next)
{
int l=edge[t].j;
if(l==pre) continue;
findAns(dp[l],v1,v2,x);
}
}
int main()
{
//freopen("data.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d %d",&n,&C);
init(n);
int a[2][4];
clArr(a);
memset(dp,-1,sizeof(dp));
ans=0;
dfs(-1,0,a);
printf("%d\n",ans);
}
return 0;
}

hdu 4616 Game的更多相关文章

  1. HDU 4616 Game (搜索)、(树形dp)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4616 这道题目数据可能比较弱,搜索都可以AC,但是不敢写,哎…… 搜索AC代码: #include & ...

  2. HDU 4616 Game(经典树形dp+最大权值和链)

    http://acm.hdu.edu.cn/showproblem.php?pid=4616 题意:给出一棵树,每个顶点有权值,还有存在陷阱,现在从任意一个顶点出发,并且每个顶点只能经过一次,如果经过 ...

  3. 【 2013 Multi-University Training Contest 2 】

    HDU 4611 Balls Rearrangement 令lcm=LCM(a,b),gcd=GCD(a,b).cal(n,a,b)表示sum(abs(i%a-i%b)),0<=i<n. ...

  4. 【转载】ACM总结——dp专辑

    感谢博主——      http://blog.csdn.net/cc_again?viewmode=list       ----------  Accagain  2014年5月15日 动态规划一 ...

  5. 【DP专辑】ACM动态规划总结

    转载请注明出处,谢谢.   http://blog.csdn.net/cc_again?viewmode=list          ----------  Accagain  2014年5月15日 ...

  6. dp专题训练

    ****************************************************************************************** 动态规划 专题训练 ...

  7. 【DP专辑】ACM动态规划总结(转)

    http://blog.csdn.net/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强, ...

  8. dp有哪些种类

    dp有哪些种类 一.总结 一句话总结: 二.dp动态规划分类详解 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. * ...

  9. (转)dp动态规划分类详解

    dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...

随机推荐

  1. linux学习笔记2-命令总结2

    权限管理命令  chmod 其他权限管理名  chgrp  chown  umask ========================================================= ...

  2. default(T)的含义

    default(T)是泛型中初始化的用法.因为对于泛型T你不知道是值类型还是引用类型,所以传参数是可能会出错.这里就要用到default(T). T t=default(T),就是初始化,值类型的话, ...

  3. Android最佳性能实践(一)——合理管理内存

    有不少朋友都问过我,怎样才能写出高性能的应用程序,如何避免程序出现OOM,或者当程序内存占用过高的时候该怎么样去排查.确实,一个优秀的应用程序,不仅仅要功能完成得好,性能问题也应该处理得恰到好处.为此 ...

  4. ListView 使用详解

    在ListView中设置Selector为null会报空指针?mListView.setSelector(null);//空指针试试下面这种:mListView.setSelector(new Col ...

  5. 使用连接(JOIN)来代替子查询(Sub-Queries) mysql优化系列记录

    使用连接(JOIN)来代替子查询(Sub-Queries) MySQL从 4.1开始支持SQL的子查询.这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查 ...

  6. ajax 跨域解决 网上资料

    PHP中运用jQuery的Ajax跨域调用实现代码,需要的朋友可以参考下   可以在页面定义一个调用方法,如下: 复制代码代码如下: function getData(){ $.getJSON(&qu ...

  7. (x&y) + ((x^y)>>1)即x和y的算数平均值

    (x&y) + ((x^y)>>1)相当于(x+y)/2 (x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值 ...

  8. java static 关键字

    static 修饰成员函数:(静态函数) 1)静态函数可以用类名和对象进行调用. 2)直接访问静态成员,但不能访问非静态成员变量. 3)非静态函数可以直接访问静态与非静态的成员.(非静态函数只能由对象 ...

  9. signalR的一些细节

    获取根目录通过AppDomain.CurrentDomain.BaseDirectory 因为不能直接获取session ,使用的替代方案如下 private static Dictionary< ...

  10. linux笔记:linux系统安装-系统分区

    分区类型: 1.主分区:最多只能有4个. 2.扩展分区:最多只能有1个:主分区+扩展分区最多有4个:不能写入数据,只能包含逻辑分区. 3.逻辑分区. 格式化: 向磁盘中写入文件系统.会附带地清空磁盘中 ...