zoukankan      html  css  js  c++  java
  • poj2279排队——杨氏矩阵与钩子公式(DP爆内存)

    题目:http://poj.org/problem?id=2279

    书上的DP做法会爆内存,尝试写了一个,过了样例。

    转载:

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll unsigned long long
    using namespace std;
    ll k,n[7],f[35][35][35][35][35];
    void cl(ll a1,ll a2,ll a3,ll a4,ll a5)
    {
        if(a1)f[a1][a2][a3][a4][a5]+=f[a1-1][a2][a3][a4][a5];
        if(a2)f[a1][a2][a3][a4][a5]+=f[a1][a2-1][a3][a4][a5];
        if(a3)f[a1][a2][a3][a4][a5]+=f[a1][a2][a3-1][a4][a5];
        if(a4)f[a1][a2][a3][a4][a5]+=f[a1][a2][a3][a4-1][a5];
        if(a5)f[a1][a2][a3][a4][a5]+=f[a1][a2][a3][a4][a5-1];
    }
    int main()
    {
        while(scanf("%lld",&k)==1)
        {
            memset(f,0,sizeof f);
            memset(n,0,sizeof n);//!!!
            if(!k)return 0;
            for(ll i=1;i<=k;i++)
                scanf("%lld",&n[i]);
            f[0][0][0][0][0]=1;
            for(ll a1=0;a1<=n[1];a1++)
            {
                if(k>=2)
                    for(ll a2=0;a2<=n[2]&&a2<=a1;a2++)
                    {
                        if(k>=3)
                            for(ll a3=0;a3<=n[3]&&a3<=a2;a3++)
                            {
                                if(k>=4)
                                    for(ll a4=0;a4<=n[4]&&a4<=a3;a4++)
                                    {
                                        if(k>=5)
                                            for(ll a5=0;a5<=n[5]&&a5<=a4;a5++)
                                                cl(a1,a2,a3,a4,a5);
                                        else cl(a1,a2,a3,a4,0);
                                    }
                                else cl(a1,a2,a3,0,0);
                            }
                        else cl(a1,a2,0,0,0);
                    }
                else cl(a1,0,0,0,0);
            }
            printf("%lld
    ",f[n[1]][n[2]][n[3]][n[4]][n[5]]);
        }
        return 0;
    }
    View Code

    然后看到了“杨氏矩阵”与“钩子公式”。

    转载:


    杨氏矩阵定义(需满足的条件/特征):(1)若格子(i,j),则该格子的右边和上边一定没有元素;
                         (2)若格子(i,j)有元素data[i][j],则该格子右边和上边相邻的格子
                        要么没有元素,要么有比data[i][j]大的元素。
    显然有同已写元素组成的杨氏矩阵不唯一,1~n组成杨氏矩阵的个数可以写出:F[1]=1,F[2]=2,
                                        F[n]=F[n-1]+(n-1)*F[n-2] (n>2)。
     
    钩子长度的定义:该格子右边的格子数和它上边的格子数之和;
    钩子公式:对于给定形状,不同的杨氏矩阵的个数为(n!/(每个格子的钩子长度加1的积))。

    于是直接用了,注意要步步约分。
    代码如下:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll unsigned long long
    using namespace std;
    int k,n[7];
    ll h[35][35],s1,s2;
    ll gcd(ll x,ll y){
    return x%y==0?y:gcd(y,x%y);}
    int main()
    {
        while(scanf("%d",&k)==1)
        {
            if(!k)return 0;
            memset(h,0,sizeof h);
            memset(n,0,sizeof n);//!
            for(int i=1;i<=k;i++)
                scanf("%d",&n[i]);
            for(int i=1;i<=k;i++)
                for(int j=1;j<=n[i];j++)
                {
                    h[i][j]=n[i]-j+1;
                    int k=i+1;
                    while(n[k]>=j)h[i][j]++,k++;
                }
            int t=0;s1=1;s2=1;
            for(int i=1;i<=k;i++)
                for(int j=1;j<=n[i];j++)
                {
                    t++;
                    s1*=t;s2*=h[i][j];
                    ll tmp=gcd(s1,s2);
                    s1/=tmp;s2/=tmp;
                }
            printf("%lld
    ",s1/s2);
        }    
        return 0;
    }
  • 相关阅读:
    LINUX
    DOCKER
    计算牛的数目
    计算a^3=b^3+c^3+d^3
    用递归计算C(m,n)
    A Mathematical Curiosity
    Who is lier?
    我的第一篇 实习报告
    R.java
    天气系统
  • 原文地址:https://www.cnblogs.com/Zinn/p/8563402.html
Copyright © 2011-2022 走看看