面试题60:n个骰子的点数(动态规划)

一、基本概念

动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。

二、基本思想与策略

基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中(视情况可以进行空间优化,即使用一维数组即可保存)。

与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。

三、适用的情况

能采用动态规划求解的问题的一般要具有3个性质:

(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)

本题的分析:
使用动态规划解决问题一般分为三步:
1、表示状态
分析问题的状态时,不要分析整体,只分析最后一个阶段即可!因为动态规划问题都是划分为多个阶段的,各个阶段的状态表示都是一样,而我们的最终答案在就是在最后一个阶段。
分析:
最后一个阶段——本题总共投了n个骰子,那么最后一个阶段的表示就为点数和出现的次数;
那么就用数组的一维来表示各个阶段;用数组的二维来表示各个阶段的点数和出现的次数;
综上:本题的状态为dp[ n ][ j ],其中n表示投了n个骰子,j表示投了n个骰子的点数和
2、找出状态转移方程
3、边界处理
在这里插入图片描述

class Solution {
public:
    vector<double> twoSum(int n) {
        vector<double>res;
        if(n<=0)return res;
        const int N=n*6+1;//数组的长度要为骰子最大和加1,因为利用下标来表示点数之和
        int dp[N];
        memset(dp,0,sizeof(dp));//全部初始化为0
        for(int i=1;i<=6;++i)
            dp[i]=1;//将第一阶段初始化为1,因为投1个骰子的时候,各个点数和出现次数都为1
        for(int i=2;i<=n;++i)
        {//当骰子数大于等于2时
            for(int j=6*i;j>=i;--j)
            {//因为使用的一维数组,所以从最后一个数开始计算,从状态转移方程来看,其值为上一个阶段的前6个值得和
                dp[j]=0;
                for(int cur=1;cur<=6;++cur)
                {
                    if(j-cur<i-1)
                    {//当点数之和不满足1*n时,即刻退出相加,无意义
                        break;
                    }
                    dp[j]+=dp[j-cur];//根据状态转移方程来求本阶段和为j出现得次数
                }
            }
        }
        int total=pow(6,n);
        for(int i=n;i<=n*6;++i)
            res.push_back(dp[i]*1.0/total);//求出现概率
        return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值