• UVA 10253 Seris-Parallel Networks


    https://vjudge.net/problem/UVA-10253

    题目

    串并联网络有两个端点,一个叫源,一个叫汇,递归定义如下。

    (1)一条单独的边是串并联网络。

    (2)若G1和G2是串并联网络,把他们的源和汇分别接在一起也能得到串并联网络。

    (3)若G1和G2是串并联网络,把G1的汇和G2的源并在一起也能得到串并联网络。

    其中规则2说的是并联,规则3说的是串联。

    串联的各部分可以改变顺序,并联的各部分可以改变顺序,都看作一种串并联网络。

    输入n,输出有多少个n条边的串并联网络。$1leqslant nleqslant 30$

    题解

    每个串并联网络都可以看成一棵树,每次串并联都生成一个节点,串并联的部分是它的儿子,叶子是单独的边

    所以问题可以转换为n个叶子能得到多少种树,兄弟顺序无关,每个节点要么没有儿子,要么大于两个儿子

    那么可以用背包,划分第一层

    dp[i][j]表示有i个叶子,现在划分有j个叶子的子树,有多少种方法

    f(x)表示含x个叶子的树有多少种,$f(x)=dp[x][x-1]$,因为每个节点要么没有儿子,要么大于两个儿子

    $dp[i][j]=sum dp[i-j*n][j-1] imes C(f(j)+n-1,n)$

    得到树以后还需要指定第一层是串联还是并联

    还有一些边界情况

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define REP(i,a,b) for(int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(int i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    ll dp[37][37],f[37];
    ll C(ll n, ll m) {
    	double ans=1;
    	REP(i,0,m) {
    		ans*=n-i;
    	}
    	REPE(i,1,m) {
    		ans/=i;
    	}
    	return ll(ans+0.5);
    }
    int main() {
    	REPE(i,0,30) dp[0][i]=1;
    	REPE(i,1,30) dp[i][0]=0,dp[1][i]=1;
    	f[1]=1;
    
    	REPE(j,1,30) {
    		REPE(i,2,30) {
    			dp[i][j]=0;
    			for(int n=0; n*j<=i; n++) {
    				dp[i][j]+=dp[i-j*n][j-1]*C(f[j]+n-1,n);
    			}
    		}
    		f[j+1]=dp[j+1][j];
    	}
    	int N;
    	while(~scanf("%d", &N) && N) {
    		printf("%lld
    ", N==1?1:f[N]*2);
    	}
    }
    
  • 相关阅读:
    RecSys Challenge 2015
    Python 多行注释
    编译型语言与解释型语言
    vs2012 提示 未能正确加载 "Visual C++ Language Manager Package" 包
    人工智能 VS 机器学习 VS 深度学习
    CV-视频分析:静态背景下的运动检测
    消费者做出购买决策的流程
    Fat jar用途
    Eclipse中打包插件Fat Jar的安装与使用
    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12643693.html
Copyright © 2020-2023  润新知