UVA 10253 - Series-Parallel Networks(数论+计数问题+递推)
2014-05-10 14:02
441 查看
题目链接:10253 - Series-Parallel Networks
白书的例题。这题也是需要把问题进行转化,一个并联可以分为几个串联,然后串联可以分成边。
如此一来,最后叶子结点种数会是n,问题转化为去分配叶子结点,使得总和为n。
书上有两种方法,一种直接去递归,利用组合数学的方式去计算答案。
一种是推出递推式:
设dp[i][j]为一共j个叶子结点的树,子树的叶子最多的为i个的情况。然后对于一颗树,枚举恰好包含i个叶子的子树为p棵,那么相当于从f[i]颗树中选出p棵树的方案数,是可重复选择的组合,组合数为:C(f[i] + p - 1, p)种,然后每种子树对应的情况数为dp[i - 1][j - p * i]
所以状态转移方程为dp[i][j] = sum{C(f[i] + p - 1, p) * d(i - 1, j - p * i)},最后答案为dp[n - 1]
,注意边界的设定,详见代码
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std; long long C(long long n, long long m) { double ans = 1; for (int i = 0; i < m; i++) { ans *= n - i; } for (int i = 0; i < m; i++) ans /= i + 1; return (long long)(ans + 0.5); } const int N = 31; int n; long long f ; long long dp ; int main() { f[1] = 1; for (int i = 0; i < N; i++) dp[i][0] = 1; for (int i = 1; i < N; i++) {dp[i][1] = 1; dp[0][i] = 0;} for (int i = 1; i < N; i++) { for (int j = 2; j < N; j++) { dp[i][j] = 0; for (int p = 0; p * i <= j; p++) { dp[i][j] += C(f[i] + p - 1, p) * dp[i - 1][j - p * i]; } } f[i + 1] = dp[i][i + 1]; } while (~scanf("%d", &n) && n) { printf("%lld\n", n == 1 ? 1 : 2 * f ); } system("pause"); return 0; }
相关文章推荐
- UVA 1073 - Glenbow Museum(数论+计数问题+递推)
- Uva 10253 - Series-Parallel Networks 解题报告(递推)
- UVA 11645 - Bits(数论+计数问题)
- UVA 11538 - Chess Queen(数论+计数问题)
- UVA 11401 - Triangle Counting(数论+计数问题)
- UVa 10253 (组合数 递推) Series-Parallel Networks
- UVA 1362 - Exploring Pyramids(计数问题+区间DP)
- UVa 11361 (计数 递推) Investigating Div-Sum Property
- UVA 10253 Series-Parallel Networks (树形dp)
- UVA 11529 - Strange Tax Calculation(计数问题)
- UVA 12123 - Magnetic Train Tracks(计数问题)
- uva 10253 - Series-Parallel Networks
- HDU1492-The number of divisors(约数) about Humble Numbers-数论(计数问题)
- uva 11481 - Arrange the Numbers(计数问题)
- UVALive 3720 Highways(组合计数、递推)
- 【递推】【组合计数】UVA - 11401 - Triangle Counting
- UVA10294项链和手镯(等价类计数问题)
- 数论基础之组合数&计数问题
- UVaLive 4847 - Binary Search Tree (与BST有关的计数问题)
- UVA 1350 - Pinary(数论+递推)