[leetcode 周赛 149] 1155 掷骰子的N种方法

目录

  • 1155 Number of Dice Rolls With Target Sum 掷骰子的N种方法

    • 描述
    • 思路
    • 代码实现

1155 Number of Dice Rolls With Target Sum 掷骰子的N种方法

描述

这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, ..., f
我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和
如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有f^d 种),模10^9 + 7后返回。

  • 示例 1:

    输入:d = 1, f = 6, target = 3
    输出:1

  • 示例 2:

    输入:d = 2, f = 6, target = 7
    输出:6

  • 示例 3:

    输入:d = 2, f = 5, target = 10
    输出:1

  • 示例 4:

    输入:d = 1, f = 2, target = 3
    输出:0

  • 示例 5:

    输入:d = 30, f = 30, target = 500
    输出:222616187

  • 提示:
    1 <= d, f <= 30
    1 <= target <= 1000

思路

这明显是个动态规划问题

  • 规律公式

d为骰子数, f为骰子面数, target为目标值, k表示当前第d个骰子掷出的数

  • 初始状态

需要投掷的目标数在单个骰子的范围内 返回1, 否则返回0

代码实现

递归实现

class Solution {
    static int MOD = (int)(1e9+7);

    public int numRollsToTarget(int d, int f, int target) {
        if (target < d | target > d*f) return 0;

        int[][] dp = new int[d+1][target+1];
        // 初始化 全-1 表示未被处理
        for (int[] dpi : dp) Arrays.fill(dpi, -1);

        return helper(d, f, target, dp);
    }

    int helper(int d, int f, int target, int[][] dp) {
        // target 超出骰子的投掷范围
        if (target < d | target > d*f) return 0;
        // 如果已经处理过 使用之前记录数据
        if (dp[d][target] != -1) return dp[d][target];
        // 当单个骰子时
        if (d==1) {
            if (target <= f && target > 0) return dp[d][target]=1;
            else return dp[d][target]=0;
        }
        // 数据没有被记录 骰子数大于等于2
        int ans = 0;
        // 对当前骰子投掷出的每个面数都进行处理
        for (int cur=1; cur <= f; cur++) {
            ans = (ans + helper(d-1, f, target-cur, dp))%MOD;
        }
        // 对数据进行记录
        return dp[d][target]=ans;
    }
}

非递归实现

class Solution {
    // 取模数 1e9 + 7
    final static int MOD = 1000000007;
    public int numRollsToTarget(int d, int f, int target) {
        if (target < d | target > d*f) return 0;

        // dp 表示当骰子为i(1~d)时j(1~target)的组合数
        // 其实长度可以是2 因为只使用上一轮的数据
        int[][] dp = new int[d+1][target+1];

        // 初始为1
        dp[0][0] = 1;
        // 从有1个骰子开始 1~d
        for (int i = 1; i <= d; i++) {
            // 当前骰子投掷数 1~f
            for (int cur = 1; cur <= f; cur++) {
                // 加上上一轮没有投掷cur时prev的组合数
                for (int prev = 0; prev+cur <= target; prev++) {
                    dp[i][prev+cur] = (dp[i][prev+cur] + dp[i-1][prev])%MOD;
                }
            }
        }

        return dp[d][target];
    }
}

原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11366818.html

时间: 2024-10-09 01:25:06

[leetcode 周赛 149] 1155 掷骰子的N种方法的相关文章

Leetcode-1155 Number of Dice Rolls With Target Sum(掷骰子的N种方法)

dp[i][j]表示前i个骰子到达数字总和j的方案数 dp[i][j] = Σdp[i-1][j-k],其中k是一个骰子能掷出的范围 1 #define _for(i,a,b) for(int i = (a);i < b;i ++) 2 3 class Solution 4 { 5 public: 6 int dp[31][1003]; 7 int numRollsToTarget(int d, int f, int target) 8 { 9 _for(k,1,f+1) 10 dp[0][k]

LeetCode 第 149 场周赛

一.一年中的第几天(LeetCode-1154) 1.1 题目描述 1.2 解题思路 比较水的一题,搞清楚平年.闰年的判定规则,就很容易做出来. 1.3 解题代码 class Solution { public int ordinalOfDate(String date) { String[] dateArray = date.split("-"); int year = Integer.parseInt(dateArray[0]); int month = Integer.parse

LeetCode 1223. 掷骰子模拟 Dice Roll Simulation - Java - DP

题目链接:1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现在,给你一个整数数组 rollMax 和一个整数 n,请你来计算掷 n 次骰子可得到的不同点数序列的数量. 假如两个序列中至少存在一个元素不同,就认为这两个序列是不同的.由于答案可能很大,所以请返回 模 \(10^9 + 7\) 之后的结果. 示例1: 输入:n =

骑士飞行棋第一版(掷骰子方法分开)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 骑士飞行棋 8 { 9 class Program 10 { 11 12 //在下面的数组存储我们游戏地图各个关卡 13 //数组的小标为0的元素对应地图上的第一格 下标为1的元素对应第二格...下标为n的元素对应n+1

掷骰子游戏窗体实现--Java初级小项目

掷骰子 **多线程&&观察者模式 题目要求:<掷骰子>窗体小游戏,在该游戏中,玩家初始拥有1000的金钱,每次输入押大还是押小,以及下注金额,随机3个骰子的点数,如果3个骰子的总点数小于等于9,则开小,否则开大,然后判断玩家是否押对,如果未押对则扣除下注金额,如果押对则奖励和玩家下注金额相同的金钱. 分析:这个题目要求灵活运用多线程的相关知识,达到点击开始按钮时,有3个线程启动,分别控制3颗骰子的转动,在3颗骰子全部转完以后,回到主线程计算游戏结果. 1 //3个线程控制3颗骰

华为历年试题(掷骰子游戏 7)

问题描述: 在掷骰子游戏中,会根据所掷数字在地图中前进几步,前进完成后需要根据当前地图位置所示的障碍进行相应操作,其中障碍表示: 1)  9:无障碍 2)  1:停掷一轮,即下轮所掷数字无效: 3)  2:后退两步,如果已经到起点不再后退: 4)  3:奖励前进一步 如果在游戏过程中,已经走到地图终点,则游戏结束.根据输入的地图数组,和5个骰子数的数组,返回最终玩家前进了多少步. 要求实现函数: void dice(int map_len, int* map, int* dice_val, in

模拟算法_掷骰子游戏&amp;&amp;猜数游戏

模拟算法是用随机函数来模拟自然界中发生的不可预测的情况,C语言中是用srand()和rand()函数来生成随机数. 先来介绍一下随机数的生成: 1.产生不定范围的随机数 函数原型:int rand() 产生一个介于0~RAD_MAX间的整数,其具体值与系统有关系.Linux下为2147483647.我们可以在include文件夹中的stdlib.h中可以看到(Linux在usr目录下,Windows在安装目录下) 1 #include<stdio.h> 2 #include<stdlib

第21本:《上帝掷骰子吗?》

第21本:<上帝掷骰子吗?> 这是一本关于量子论的科普读物,不过作者曹天元把一系列人物和实验用一种小说的形式讲 述了下来,很感叹作者深厚的理论知识和文字功底.这本书在豆瓣上评分在9.3-9.4,我的GTD阅读清单是按照评分顺序来整理的,超过9分的读物如果不 优先阅读真有点对不起书名里的上帝. 这类书既然是科普知识类的书,就很难找到可以执行的行动,这些知识体系能让你的视野开阔,当思考一个问题时不能被其表面现象所迷惑,任何一个定律都 不是绝对适用的.在读到能量不是连续的,而是一份一份的,再想到计算

上帝掷骰子吗:量子物理史话

body { font-family: Microsoft YaHei UI,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-serif,宋体, PMingLiU,serif; font-size: 10.5pt; line-height: 1.5; } html, body { } h1 { font-size:1.5em; font-weight:bold; } h2 { font-size:1.4em; font-weight:bo