zoukankan      html  css  js  c++  java
  • USACOTrainning.Cow Pedigrees

    这题算是整死了,大大的Debug了一番。

    大意是一个二叉树,点的度数只能为0或2,给出节点数和数的高度,问有多少种树,即树的计数问题。

    用的是DP,f(i,j)表示i个节点构成j高度的树的个数,其中在转移的时候还需要small(i,j),表示i个节点的高度小于等于j的树的个数。

    然后f(i,j)=f(left,j-1)*small(right,j-2)+small(left,j-2)*f(right,j-1)+f(left,j-1)*f(right,j-1)

    1 #include <iostream>
    2 #include <string>
    3 #include <string.h>
    4 #include <vector>
    5 #include <math.h>
    6 #include <time.h>
    7  using namespace std;
    8
    9  const int M = 9901;
    10
    11  int small[205][105];
    12  int s[205][105];
    13  int no = 0;
    14
    15 //contruct a depth(<=k) tree with n nodes
    16 int getSmall(int n, int k)
    17 {
    18 //if(n % 2 == 0) return 0;
    19 int res = 0;
    20 if(n == 1 && k >= 1) return 1;
    21 if(n == 0 || k <= 0) return 0;
    22 if(small[n][k] != -1) return small[n][k];
    23 for(int i = 0; i <= n - 1; i++)
    24 {
    25 int left = i;
    26 int right = n - 1 - i;
    27 res += getSmall(left, k - 1) * getSmall(right, k - 1);
    28 res %= M;
    29 }
    30 small[n][k] = res;
    31 return res;
    32 }
    33
    34 int dfs(int n, int k)
    35 {
    36 //if(n % 2 == 0) return 0;
    37 int res = 0;
    38 if(n == 1 && k == 1) return 1;
    39 if(n == 0 || k == 0) return 0;
    40 if(s[n][k] != -1) return s[n][k];
    41 for(int i = 0; i <= n - 1; i++)
    42 {
    43 int left = i;
    44 int right = n - 1 - i;
    45 int t = res;
    46 res += dfs(left, k - 1) * getSmall(right, k - 2);
    47 res %= M;
    48 res += dfs(right, k - 1) * getSmall(left, k - 2);
    49 res %= M;
    50 res += dfs(left, k - 1) * dfs(right, k - 1);
    51 res %= M;
    52 }
    53 s[n][k] = res;
    54 return res;
    55 }
    56
    57 int main()
    58 {
    59 //freopen("nocows.in", "r", stdin);
    60 //freopen("nocows.out", "w", stdout);
    61
    62 int n, k;
    63 scanf("%d%d", &n, &k);
    64 memset(small, -1, sizeof(small));
    65 memset(s, -1, sizeof(s));
    66 printf("%d\n", dfs(n, k));
    67 }

    到dp的转移方法和状态表示清楚后,其实就简单了,可是这里却出现了很悲剧的结果,花了很长的时间终于找出了原因。

    getSmall函数中,原来是这样:

    1 if(n == 1 && k >= 1) return 1;
    2 if(n == 0 || k == 0) return 0;

    这样没处理K<0的情况,这在dfs中是不会出现的,但这里由于从dfs中传递过来的,

    res += dfs(left, k - 1) * getSmall(right, k - 2);

    这里的k可能为1,所以就可能传进一个负数K了。

    在test 7挂掉了,数据是这样的:N=172,K=44,按理来说根据二叉树的性质,这里能推倒出N应为一个奇数,偶数时应该为ANS应该为0.

    然后结果却大于0,Debug中发现small[8][42]为1,可没有地方能让它赋值为1啊。。。

    这就是因为传入了负数K,递归的次数会应为N而有限,所以递归没爆栈,可是当n=8,k=-63时,发生了件出乎意料又情理之中的事情。

    small[8][-63]=c时,赋的就是small[8][42]的值。

    通过这次Debug,晓得越界真是件可怕的事情。

    贴AC后的爽图,娘的。

    感谢:

    http://hi.baidu.com/leokan/blog/item/a8fca034599fd0b3d0a2d3bd.html

  • 相关阅读:
    Web后门工具WeBaCoo
    苹果内存取证工具volafox
    PlayMaker GUI的Normalized
    Arduino可穿戴教程之第一个程序——选择端口(三)
    缩略图信息提取工具vinetto
    jquery的defer
    toDo
    瀑布流案例
    js基本知识6
    js基本知识5
  • 原文地址:https://www.cnblogs.com/litstrong/p/1725713.html
Copyright © 2011-2022 走看看