七月解题日志1

 7月集训前(截至7月17日)
July_1
POJ1240 Pre-Post-erous!

http://acm.pku.edu.cn/JudgeOnline/problem?id=1240


  对于一棵m叉树,只知道先根序遍历和后根序遍历序列是不能得到确切的树的结构的,但是可能的树的结构有多少种?
  
  递归地推:
  如果根有n棵子树,则共有C(m,n)种选择;
  然后再乘以每棵子树可能的结构数目:乘法原理。

  根据先根序遍历和后根序遍历序列可以划分子树和得到当前结点有多少子树,这个不难想。




July_3
POJ Picnic Planning

http://acm.pku.edu.cn/JudgeOnline/problem?id=1639

  度限制最小生成树。

  lrj《算法艺术与程序设计竞赛》上有比较清楚解法,我看懂后照着敲了一个,结果花了一个下午才写出来,整整300+行(我写代码向来冗余,待整理),好在做出来了。

  我的解法思路(大致照lrj的解法):
 1 先Prim+heap求最小生成树块;
 2 然后添加0到各连通块的最小边;
 3 然后通过h(t)求h(t+1)——关键部分:
    枚举2中未选的0的邻边,然后在形成的环中找最大边删除(这里跟lrj的不一样,我作了一遍dfs找最大边,最后删边也用dfs实现)。
   终止条件为0的度数到达k或上边的情况不能使生成树总长减小。


  这套方法太麻烦,由于题目数据范围小,可以考虑换Kruscal实现。


July_4
POJ1041 John's trip

http://acm.pku.edu.cn/JudgeOnline/problem?id=1041
  经典欧拉回路的题。
  这个题目是为了攒一份欧拉回路标程写的——这个题目是求欧拉回路而且多两项要求:一是起点必须是第一条路径的较小标号点,二是求出来的回路序列要是最小(每条路径有一个标号)。
  原来在USACO写过一个求欧拉回路要求访问点序列最小的的欧拉路,当时用矩阵实现,这样欧拉路/欧拉回路基本会写了——不过如果要非递归实现的话……

  这个题目写了半个上午——毕竟要求序列最小这一点换了好几种想法……


July_12
炮兵阵地

source Noi2001 day2
http://acm.pku.edu.cn/JudgeOnline/problem?id=1185

  这个题基本算我写的第一个状态压缩DP的题目。

   原来的时候把状态压缩DP想得很高深,一直不敢动,今天下定决心通过以前看过的一些思想的总结来写这一类题目,写完这个题后初步感觉状态压缩DP的主要特点就是状态压缩(废话!但理解这句话用了这么几个月):除了对状态的表示要压缩起来表示之外与普通DP没什么两样。

 这个题目是个赤裸裸的状态压缩DP:直接按照题意状态转移就可以了——用二进制表示地形和当前行炮兵布局,一个状态用两层表示:上一行和当前行的炮兵布局。难想的一点是状态怎么压缩:其实可以用数组把一行的合法布局记录下来,这样100列也就60种状态,记录两行状态数不过3600,复杂度O(n*num^3)(num为状态数),最大100*60*60*60=216000,加上一些判断其实很快的。

 Wa了一次,忘记一直取最大值了。



Jul_13
POJ2817 WordStack

http://acm.pku.edu.cn/JudgeOnline/problem?id=2817

  经典状态压缩DP。
  
  求最长最长汉密尔顿路(非回路)。由于昨天开始做了几个状态压缩的题目后,对这类题有点理解,加上这个题目基本上是赤裸裸的状态转移,很快写过。
  Wa了一次:由于开始求的是最长公共子序列长度(其实是最大对应相同的字母数)。


July_14

POJ 3164 Command Network


  这个题目就是经典的最小树形图。
 
  前几天看到这个问题的朱刘算法好像很容易理解、很清晰,加上今天做题不顺就写了。
  
TJU 2248 也是求最小树形图,先做的这个(这个赤裸裸!)
http://acm.tju.edu.cn/toj/showp2248.html

  写了一个下午,原因是头脑不清晰,代码风格也不好,写来写去开始一直TLE,后来找了hdu的一个人的标程,发觉自己的思路没错,基本一样……
 查了好久,发现在找环后标记时标记了缩点为已经从图中去除!

  改了后WA,错误在于缩点时入边出边不分——对于入边要减去dis[ pre[u] ][u]!

  还有网上推荐的uva11185也过了
http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&page=show_problem&problem=2124


  总结下做法:网上大家贴的算法都很清晰,有个图更是明了,不过代码还是长了点。。
wy的总结:
http://hi.baidu.com/wywcgs/blog/item/a1ce10f4a8fa366fdcc47462.html

算法图解:
https://p-blog.csdn.net/images/p_blog_csdn_net/huangwei1024/tree_graph.JPG




July_15

POJ3368 Frequent values


  我做得最暴力的线段树了!本来想试试结果过了。标准解法是RMQ的st算法。

  其实感觉这两个东西还是很相像的,觉得如果不是卡内存时间过紧的话,一般的RMQ(就是我目前能作的白痴RMQ)都可以用线段树干掉。

  太暴力了,线段树上直接维护了最左边和最右边的值和出现次数和本区间的最大重复值的次数——5个数值!!!然后用RMQ的方法合并,就跟我们正常思维一样,新合并区间的最大数值出现次数会是左右节点和中间数值的重复次数中最大的一个,思路清晰就好写了。


POJ3321 Apple_tree
http://acm.pku.edu.cn/JudgeOnline/problem?id=3321

  第一次做树状数组的题目,不过值得学习的却是树遍历的特点。

  这个题目开始以为用线段树做(其实是可以的!) 由于想了很久也没有想到怎么来将树的结构排序,就看了Discuss,发现树状数组也可以——想到从没写过,然后就去找文章看……

  题目关键不在数据结构(用的是标准的树状数组或线段树),关于排序的思想很重要:先根序遍历,对每个节点记录其序号和其子树的最大序号(也就是标记一棵树遍历的第一个和最后一个节点的遍历序号st、ed)。
  统计一个节点为根的树中数目时,直接计算1到st-1、ed的数组和然后相减即可。


POJ1204 Word Puzzles

  这个题目其实还是个简单题——直接写个Trie就好了。不过我还是RE了不少次数:原因是忘记初始化指针指向NULL了!!!!弱智啊~~
  
 
  不过做了这个题目我在POJ上的little id-->R2D2的题数就与littlekid这个帐号一样了。将两个号一合计:在POJ上也算AC了有283题了,+U,fighting!




July_16

POJ1037

动态规划+递推。

  这个题目去年第一次看到就推出了那个算n个栅栏以第i短的为第一根下一根放短的or长的栅栏的方案数。

f[n][1][0] = 0; f[1][1][1] = 1;
f[n][i][0] = f[n-1][i-1][0]+f[n-1][i-1][1];
f[n][i][1] = f[n][n+1-i][0];

 麻烦的是求具体方案。

 求第一根栅栏还是很好求的——直接从f[n][1][0]、f[n][1][1]……一直减,找到i和类型(短/长)。

 维护一个集合为未选栅栏
 中间的递推比较麻烦:若类型为短,从1减、否则从上次得到的i向上减。(-f[t_len{后边长度}][i][type])。
 找到位置i后输出第i小的数。

 总之这个题目很考递推能力——推了几个小时还是错了一点,最后discuss里那个人的程序递归实现的还是帮了大忙!

 这个题目思想很好,以后要回来温习。


July_16

POJ 1077 Eight

经典搜索题。

这个题目可以用一般BFS,A*,双向BFS……等方法做。

原来写过BFS版本,今天写了个双向BFS——毕竟听说过这个名词以来还没写过。

其实双向BFS真的很简单:就是BFS的时候同时从目标和初始状态做BFS,关键的地方在于判断当前搜索出来的状态是否在另外一棵搜索树中出现(这里借用Hash判断,对每个状态hash时记录其在队列中位置,利用位置关系判断——比如我开一个队列,初始状态从0向后[head1,tail1),目标状态从最后向前(tail2,head2], 如果一个节点出现在另外一个区间,就找到解了)。

这样0ms,普通600+ms,真的很强大……

不过很费空间(本人不幸0ms用空间最多),下次学了A*再做。



July_17

July_1195

POJ1195 Mobile phones

source IOI2001

  经典二维树状数组题。

  前边做过一个一维的树状数组题目,就想当然地扩展到二维了,结果郁闷地WA了几次。

  找来解题报告看,发现二维的树状数组麻烦多了,要控制的东西还不少:不过目前还是不很明白……

  照着别人程序写了个,AC了,

  希望能早日领悟到统计问题的精髓部分。
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值