其他分享
首页 > 其他分享> > 1155. 掷骰子的N种方法

1155. 掷骰子的N种方法

作者:互联网

1155. 掷骰子的N种方法

题目描述

这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, ..., f。

我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和。

如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有 f^d 种),模 10^9 + 7 后返回。

思路分析(二维)

这个题是动态规划问题,参考一篇文章吃透背包问题!(细致引入+解题模板+例题分析+代码呈现)

的分析思路,首先,这个是一个分组背包问题,然后又是组合问题。分组背包的特点是在每个数的选择上都有好几个选择,可以把每个筛子当成普通背包的重量,不过这个重量是看可以变得。可以用三个循环,前两个循环按照题目按照0/1背包、完全背包和组合背包的要求写,第三个循环时选择重量(在本题中就是骰子的点数)。对于本题。最外面循环是骰子的个数d,然后 中间一层是target,由于这个每个骰子是不可重复用的,因此taget循环用倒序(如果是二维dp那么正序也可以),然后最后一层便是点数的循环f。本题中用dp[i] [j]表示用前i个骰子得到目标和j的组合数目,那么有dp[i] [j]+=dp[i] [k],k>=1&&k<=j

代码实现

class Solution {
public:
    
    int numRollsToTarget(int d, int f, int target) {
        const int mod=1000000007;
        vector<vector<int>>dp(d+1,vector<int>(target+1,0));
        //初始化
        dp[0][0]=1;
        //对于骰子遍历
        for(int i=1;i<=d;i++)
        {
            //对于target的遍历
            for(int j=target;j>=1;j--)
            {
                //对于骰子的遍历,细节1:j>=k
                for(int k=1;k<=f&&j>=k;k++)
                {
                    dp[i][j]+=dp[i-1][j-k];
                    dp[i][j]%=mod;
                }
            }
        }

        return dp[d][target];
    }
};

思路分析(一维优化)

对于一维优化,设定dp[j]为目标和为j的组合数目。相比于二维,需要注意的一个细节便是骰子都必须用上,因此如果用假如两个骰子那么得到的最小数便是2,那么就需要dp[j],j<i需要设置为0(二维dp不用担心),另外一个细节是骰子不能摇出来0(所以不能用dp[j]直接加,需要从0开始加)。

class Solution {
public:
    
    int numRollsToTarget(int d, int f, int target) {
        const int mod=1000000007;
        vector<int>dp(target+1,0);
        dp[0]=1;
        for(int i=1;i<=d;i++)
        {
			//细节1:倒序,这样加的是上一层的
            for(int j=target;j>=i;j--)
            {
                //细节2:只加当点数为1—k的
                int sum=0;
                for(int k=1;k<=f&&j>=k;k++)
                {
                    sum+=dp[j-k];
                    sum%=mod;
                }
                dp[j]=sum;
            }
            //细节3:小于筛子个数的设置为0
            for(int j=0;j<i;j++)
                dp[j]=0; 
        }
        return dp[target];
       
    }
};

标签:骰子,背包,target,1155,掷骰子,int,点数,方法,dp
来源: https://www.cnblogs.com/zengfanlu/p/14868883.html