zoukankan      html  css  js  c++  java
  • [CF295C] Greg and Friends

    Description

    有一只载重为 (k le 5 imes10^3) 的船在两岸之间往返,有 (n le 50) 个人要过河,每个人的体重只能使 (50)(100),问最少的来回次数以及对应的方案数。

    Solution

    (f[i][j][0/1]) 表示对岸已经有 (i)(50)(j)(100) 时最少的航行次数,(g[i][j][0/1]) 为对应的方案数

    枚举本次走的 (k,l) 个数,利用组合数进行转移即可

    最多转移 (2n) 轮一定能完事,复杂度 (O(n^5))

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 55;
    const int dbg = 1;
    const int mod = 1e9+7;
    
    int n,m,a,b;
    int f[N][N][2],g[N][N][2],nCr[N][N],e[N][N][2];
    
    void readall()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            int t;
            cin>>t;
            if(t==50) ++a;
            else ++b;
        }
    }
    
    void update(int a,int b,int &c,int &d,int &e)
    {
        if(a<c)
        {
            c=a;
            d=b;
            e=1;
        }
        else if(a==c)
        {
            d+=b;
            d%=mod;
        }
    }
    
    void presolve()
    {
        nCr[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            nCr[i][0]=1;
            for(int j=1;j<=i;j++)
            {
                nCr[i][j]=(nCr[i-1][j]+nCr[i-1][j-1])%mod;
            }
        }
    }
    
    void solve()
    {
        memset(f,0x3f,sizeof f);
        f[0][0][0]=0;
        memset(g,0xff,sizeof g);
        g[0][0][0]=1;
        e[0][0][0]=1;
        for(int v=1;v<=2*n;v++)
        {
            for(int i=0;i<=a;i++)
            {
                for(int j=0;j<=b;j++)
                {
                    for(int k=0;i+k<=a;k++)
                    {
                        for(int l=0;j+l<=b;l++)
                        {
                            if(k==0&&l==0) continue;
                            if(k*50+l*100>m) continue;
                            update(f[i][j][0]+1,g[i][j][0]*nCr[a-i][k]%mod*nCr[b-j][l]%mod,f[i+k][j+l][1],g[i+k][j+l][1],e[i+k][j+l][1]);
                        }
                    }
                }
            }
            for(int i=0;i<=a;i++)
            {
                for(int j=0;j<=b;j++)
                {
                    for(int k=0;i-k>=0;k++)
                    {
                        for(int l=0;j-l>=0;l++)
                        {
                            if(k==0&&l==0) continue;
                            if(k*50+l*100>m) continue;
                            update(f[i][j][1]+1,g[i][j][1]*nCr[i][k]%mod*nCr[j][l]%mod,f[i-k][j-l][0],g[i-k][j-l][0],e[i-k][j-l][0]);
                        }
                    }
                }
            }
            if(f[a][b][1]<1e9)
            {
                cout<<f[a][b][1]<<endl<<g[a][b][1]<<endl;
                return;
            }
        }
        {
            cout<<-1<<endl<<0<<endl;
        }
    }
    
    signed main()
    {
        readall();
        presolve();
        solve();
    }
    
  • 相关阅读:
    JavaScript节点介绍
    JavaScript DOM操作案例tab切换案例
    Binder系列10—总结
    Binder系列9—如何使用AIDL
    Binder系列8—如何使用Binder
    Binder系列7—framework层分析
    Binder系列2—Binder Driver再探
    Binder系列1—Binder Driver初探
    Binder系列3—启动ServiceManager
    Binder系列4—获取ServiceManager
  • 原文地址:https://www.cnblogs.com/mollnn/p/13582648.html
Copyright © 2011-2022 走看看