YY_More

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

2011年7月9日

摘要: NOI原题,下了数据,都过了。但是OJ现在挂了。。。首先,脑袋的数量都是唬人的。如果至少3个脑袋的话,完全可以做到不让两个小头在一起(不过当只有2个头的时候得特别考虑)。所以我们就把状态设计成F[i][j][k]是以i为根的树里有j个大头吃的果子(k=1时i被大头吃,0时被小头吃)。转移方程很好像,看程序就好了。我没有转化成二叉树做,其实本质上来说还是树形依赖背包嘛,只不过要讨论父亲节点和儿子节点被那个脑袋吃而已。//By YY_More#include<cstdio>#include<algorithm>using namespace std;const int IN 阅读全文
posted @ 2011-07-09 11:23 YY_More 阅读(748) 评论(0) 推荐(0) 编辑

2011年7月8日

摘要: 这是IOI2005的原题。首先打眼一看,这个肯定是树形动规嘛(至少我是这么认为的)。首先想的是用F[i][j]表示i为根的子树里建j个的最小费用。但是转移不动= =于是就增加一维,这一维是距离i最近的建造了伐木场的祖先。同时,我们使用转换成二叉树和记忆化搜索的办法,可以减少编程复杂度和无用状态。转移是F[i][j][v]=min(F[lch[i]][p][v]+F[rch[i]][q][v]+dis(i,v)//不在i建p+q=j,F[lch[i]][p][i]+F[rch[i]][q][v]//在i建p+q+1=j)(//By YY_More#include<cstdio>#in 阅读全文
posted @ 2011-07-08 14:42 YY_More 阅读(533) 评论(0) 推荐(0) 编辑

2011年7月6日

摘要: 我才发现我这么水。原打算随便再找道题早上热身,结果WA一直到现在。改了一天,结果发现是最白痴的错误。这道题本质上还是树形的背包,但是枚举的时候要多考虑以某儿子为根的树被整个砍掉的情况。//By YY_More#include<cstdio>#include<iostream>using namespace std;struct edge{ int point; edge *next;};edge *g[151];int N,P,x,y,root,F[151][151],goin[151];int INF=200;void insert(int father,int so 阅读全文
posted @ 2011-07-06 16:47 YY_More 阅读(200) 评论(0) 推荐(0) 编辑

摘要: 这也是道树形的背包,很恶心。以至于我都不想解释了。。。都在程序里。//By YY_More#include<cstdio>#include<cstring>struct edge{ int point; edge *next;};int N,K,a,b,W[201],F[101][201],H[101][201];bool ed[101];edge *g[101];void insert(int from,int to){ edge *p=new edge; (*p).next=g[from]; g[from]=p; (*p).point=to;} void dp(in 阅读全文
posted @ 2011-07-06 00:21 YY_More 阅读(337) 评论(0) 推荐(0) 编辑

2011年7月5日

摘要: 做道水树形动规。。。也不解释。看程序什么都懂了。//By YY_More#include<cstdio>#include<algorithm>using namespace std;struct edge{ int point; edge *next;};edge *g[1500];bool ed[1500];int yes[1500],no[1500],N,h,k,a;void insert(int from,int to){ edge *p=new edge; (*p).next=g[from]; (*p).point=to; g[from]=p;};void dp 阅读全文
posted @ 2011-07-05 20:21 YY_More 阅读(224) 评论(0) 推荐(0) 编辑

2011年7月4日

摘要: 水背包。。。做道水题。。。不解释。。。//By YY_More#include<cstdio>#include<cstring>struct edge{ int point; edge *next;}; int N,M,a,b,V[201],F[201][210];edge *g[201]; void insert(int fa,int so,int data){ edge *p=new edge; (*p).point=so; (*p).next=g[fa]; g[fa]=p; V[so]=data;}; void dp(int x){ F[x][0]=0; edge 阅读全文
posted @ 2011-07-04 18:02 YY_More 阅读(269) 评论(0) 推荐(0) 编辑

摘要: 找了几道背包做了一下。这道题是让求出使得没有被装进背包的物品装不进背包的方案数。。。我们把物品体积排下序。可以枚举装不进背包的最小的物品。那么这意味着比这个物品小的一定会装进背包,比这个物品大的就是01背包的模型了。那么i为最小进不了物品时,对应的方案数就是:以比i大的物品做一个容积为(背包容积-sum(<i))的01背包,使得剩余的容积不足Vi的方案数。//By YY_More#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int N,M,t,sum,an 阅读全文
posted @ 2011-07-04 11:55 YY_More 阅读(284) 评论(0) 推荐(0) 编辑

2011年7月2日

摘要: 这个是NOI2003的原题,是一道树形动态规划。题意就是找到树上的3个点a,b,c,使得ab<ac且ab+bc最大。我们发现ab和bc总能抽象成一个T的形状,那么设最中间那个交叉点为x,那么ax,bx,cx肯定是从x连出去的3条最大的边。我们按两个方向DP,维护3个值和最大值的来源,最后枚举交叉点即可。其实这道题跟树网的核加强版差不多,多维护一个值而已。不过我发现我写的这几道树形动规程序都很慢,不清楚是哪里做的不规范。唉~~~这里抱怨一下:为什么有的OJ要用lld,有的要用I64d呢?为什么我的RP这么差,在每个地方都试了两次。。。(巴蜀上是I64d)//By YY_More#inclu 阅读全文
posted @ 2011-07-02 22:45 YY_More 阅读(276) 评论(0) 推荐(1) 编辑

摘要: 一道基础的树形动态规划。就是求从树里每个点出发的最长链的长度。考虑到这个最长链可能是从子节点来的也可能是从父节点来的,我们进行两次DFS。第一次是从儿子到父亲方向,维护从每个节点到儿子节点方向的最长链和次长链。第二次维护从父亲方向来的最长链,有两种情况,如果父亲节点第一次DFS得到的最长链来自正在遍历的子节点,则从父亲的次长链转移,否则直接从父亲的最长链转移。问题是我的程序怎么那么慢呢。。。简化掉一些memset之后还是100+ms,奇怪。//By YY_More#include<cstdio>#include<cstring>struct treetype{ int 阅读全文
posted @ 2011-07-02 10:14 YY_More 阅读(283) 评论(0) 推荐(1) 编辑

2011年7月1日

摘要: 看到八中OJ上面吧NOIP原题的n=300扩大到了n=500000,就研究了一下O(n)的算法。首先要确定的是如果有好几条直径的话,任意一个上面都会有一个核。 证明的话可以这么想:先考虑有两条直径的情况,因为这是一棵树,所以两个直径肯定有重合的部分,如果核在重合的部分就不用说了。如果在其他地方呢,那么是不可能的= =!为什么呢?先把两条直径简化成>--<的形状,那么重合的部分的一侧的两条链是对称的。如果核在<上,那其偏心距肯定在>--上。这么看来的话肯定不如核在中间部分优。怎么找到一条直径呢,最简单的办法就是先任选一个点开始BFS/DFS,找到一个最远的点,这个点一定是 阅读全文
posted @ 2011-07-01 22:26 YY_More 阅读(2115) 评论(0) 推荐(1) 编辑