zoukankan      html  css  js  c++  java
  • 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);
    	}
    }
    
  • 相关阅读:
    Android数据库升级,数据不丢失解决方案
    Android项目中单实例数据库类,解决database is locked
    Android彩蛋效果,微信彩蛋效果
    Android性能优化
    Unable to execute dex: method ID not in [0, 0xffff]: 65536
    Android下载速度计算
    Android中不混淆类中函数
    Android中Parcelable接口用法
    开启Ubuntu Linux下VirtualBox访问USB功能
    touch移动触屏滑动事件
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12643693.html
Copyright © 2011-2022 走看看