zoukankan      html  css  js  c++  java
  • acdream 1014: Dice Dice Dice DFS枚举

    1014: Dice Dice Dice

    Time Limit: 10 Sec  Memory Limit: 128 MB 

    Description

    There are 1111 ways in which five 6-sided dice (sides numbered 1 to 6) can be rolled so that the top three numbers sum to 15. Some examples are: 
     
    D1,D2,D3,D4,D5 = 4,3,6,3,5 
    D1,D2,D3,D4,D5 = 4,3,3,5,6 
    D1,D2,D3,D4,D5 = 3,3,3,6,6 
    D1,D2,D3,D4,D5 = 6,6,3,3,3 
     
    Now we have a extended problem:
    In how many ways can n m-sided dice (sides numbered 1 to m) be rolled so that the top k numbers sum to p?

    Input

    There are multiple test cases. (about 15 groups)
    For each test case, there is only four integers n, m, k, p. (1 <= k <= n <= 20, 3 <= m <= 12)
     

    Output

    For each test case, output an integer indicating the answer.

    Sample Input

    5 6 3 15 6 6 3 15

    Sample Output

    1111 7770

    HINT

     

    Source

    dut200901102

    题目大意: 一个m面的骰子,抛n次,得到序列。统计其中k次最大的和为p的序列数。

    解题思路:直接枚举序列,时间总共需要n^m = pow(20,12), 这样时间上不符合。

                      通过枚举m个值出现的次数,来降低时间复杂度。

         因为k,n,m的值都比较小,我们可以在区间[m,1]中枚举出k个满足和为P的序列的个数,且其中最小值为x,然后再在区间[x,1]枚举出n-k个数的数量。

         最后得出[1,m]区间各个数出现的次数,则当前合法序列其排列数为  n! / { num1!*num2!*..*numM! } (其中num>0)  

    View Code
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<string.h>
    typedef long long LL;
    
    int num[30], cnt[30], size[30];
    int n, m, K, P;
    LL fac[21] = {0,1}, ans;
    void GetFact(){
        for(int i = 2; i <= 20; i++)
            fac[i] = fac[i-1]*i;
    //    for(int i = 1; i <= 20; i++)
    //        printf("%d: %lld\n", i, fac[i]);
    }
    
    void dfs_NK( int x , int CurNum , int MaxNum )
    {
        if( CurNum == MaxNum )
        {
            LL res = fac[n];    
            for(int i = m; i > 0; i--)
            {
                int t = num[i]+cnt[i];
                if( t > 0 )    res /= fac[t];    
            }    
            ans += res;    
        }
        else{
            for(int i = 0; x > 0 && i <= MaxNum-CurNum; i++)
            {
                cnt[x] = i;
                dfs_NK( x-1, CurNum+i, MaxNum );    
                cnt[x] = 0;     
            } 
        }
    }
    void dfs_K( int x, int CurNum, int CurSum)
    {
    //    printf("CurNum = %d\n", CurNum);
        if( CurNum == K && CurSum == P ){
    /*        for(int i = m; i > 0; i--)
            {
                printf("num[%d] = %d,", i, num[i]);
            }    
            printf("\n");*/    
            memset( cnt, 0, sizeof(cnt));    
            dfs_NK( x+1, 0, n-K );
            return;
        }
        for(int i = 0; x > 0 && i <= K-CurNum; i++)
        {
            if( CurNum + i <= K && CurSum + i*x <= P )
            {
                num[x] = i;
                dfs_K( x-1, CurNum+i, CurSum+i*x );
                num[x] = 0;    
            }     
        }
    }
    
    int main(){
        GetFact();
        while( scanf("%d%d%d%d",&n,&m,&K,&P) != EOF)
        {
            if( ceil(1.*P/m) > K ) printf("0\n");
            else{
                ans = 0;    
                memset( num, 0, sizeof(num));    
                dfs_K( m, 0, 0 );      
                printf("%lld\n", ans);    
            }
        }
        return 0;
    }
  • 相关阅读:
    Hadoop2.x集群动态添加删除数据节点
    HDFS中块状态分析
    procedure of object(一个特殊的指针类型)
    设计模式导语一
    Delphi中的容器类(二)
    让AlphaControls改变DevExpress皮肤
    Delphi中的容器类(一)
    Delphi 的RTTI机制浅探
    重写AuthorizeAttribute实现自己的权限验证
    含有HttpContext元素的单元测试
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2808993.html
Copyright © 2011-2022 走看看