zoukankan      html  css  js  c++  java
  • Codeforces 509F Progress Monitoring:区间dp【根据遍历顺序求树的方案数】

    题目链接:http://codeforces.com/problemset/problem/509/F

    题意:

      告诉你遍历一棵树的方法,以及遍历节点的顺序a[i],长度为n。

      问你这棵树有多少种可能的形态。

      遍历方法:

        used[1 ... n] = {0, ..., 0};

        procedure dfs(v):

          print v;

          used[v] = 1;

          for i = 1, 2, ..., n:

            if (a[v][i] == 1 and used[i] == 0):

              dfs(i);

        dfs(1);

    题解:

      表示状态:

        dp[i][j] = numbers

        表示a[i to j]这些节点,以a[i]为根所能构成的树的方案数。

      找出答案:

        ans = dp[1][n]

      如何转移:

        dp[i][j]一定以a[i]为根,且第一个访问的子节点一定是a[i+1]。

        所以将dp[i][j]分为三部分:

          (1)根节点a[i]

          (2)最左边的一棵子树a[i+1 to k]

          (3)右边剩下的一堆节点a[k+1 to j]

        那么根据乘法原理:

          dp[i][j] = ∑ dp[i+1][k]*右边一堆节点的方案数

        然而遍历是根据节点编号从小到大访问儿子节点的。

        这就要求,对于后面的一堆节点,如果其中某一个a[x]要和a[i+1]在同一层,那么一定要有a[i+1]<a[x]。

        又因为对于右边的一堆节点来说,最先访问到的肯定是a[k+1]。

        所以就是要保证:a[i+1]<a[k+1] or a[k+1]不存在

        这样就不用管后面的节点了,爱咋分咋分……

        接下来考虑如何求右边一堆节点的方案数。

        a[k+1 to j]形成森林的方法数 = a[k to j]以a[k]为根的子树的方法数。

        所以右边一堆节点的方案数 = dp[k][j]

        最终就是:

          if(a[i+1]<a[k+1] || k==j)

            dp[i][j] += dfs(i+1,k)*dfs(k,j);

          用记忆搜搞就行。

      边界条件:

        dp[i][i] = 1

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 505
     5 #define MOD 1000000007
     6 
     7 using namespace std;
     8 
     9 int n;
    10 int a[MAX_N];
    11 long long dp[MAX_N][MAX_N];
    12 
    13 long long dfs(int i,int j)
    14 {
    15     if(i==j) return 1;
    16     if(dp[i][j]!=-1) return dp[i][j];
    17     dp[i][j]=0;
    18     for(long long k=i+1;k<=j;k++)
    19     {
    20         if(a[i+1]<a[k+1] || k==j)
    21         {
    22             dp[i][j]+=dfs(i+1,k)*dfs(k,j);
    23             dp[i][j]%=MOD;
    24         }
    25     }
    26     return dp[i][j];
    27 }
    28 
    29 int main()
    30 {
    31     cin>>n;
    32     for(int i=1;i<=n;i++) cin>>a[i];
    33     memset(dp,-1,sizeof(dp));
    34     cout<<dfs(1,n)<<endl;
    35 }
  • 相关阅读:
    ABAP TCode
    SAP 常用的事务代码
    SAP FI TCode
    Little Tutorials的一篇文章断言:UML(统一建模语言)正在死亡:
    SAP PP TCode
    [ZT]解密中国IT人十大职业现状
    User Exit Query
    SAP客户端多语言设置
    一个女CIO的诞生
    DIY防奸手册之 主流硬盘型号解惑篇
  • 原文地址:https://www.cnblogs.com/Leohh/p/8206941.html
Copyright © 2011-2022 走看看