• 【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)


    一开始用了模拟的方法,DFS来搜索,但是因为当n很大的时候有很多的重复计算,因为会踏过重复的点进行重复的操作,而且不能不走这些重复的路径,因为没有存储结果,最后只过了三个点。

    考虑到重复的路径,所以想到利用动态规划。

    可以认为dp[i][j]表示的是 从左上角开始走,走出以(1,1)到(i,j)为两个端点的棋盘中拿到牙签袋的期望。

    画图可以知道,因为每次都是斜向下走。走出 i,j棋盘,可以是先走出比这个棋盘小的36种小棋盘的任何一种,然后再吃到在小棋盘和i,j中的某一个,拿到的牙签期望。

    (如果走出了一个小棋盘,还可以再出大棋盘之前吃两个的话,这种情况已经被在其他的小棋盘(比前面说的小棋盘大一点)算过了,所以不用考虑)

    所以这样的话就是

    dp[i][j] = E {(dp[i-t][j-k]+1) * 1 / 36} ; t,k从1到6 E表示求和

    注意这里需要处理一下就是因为i-t和j-k有可能不存在,所以dp是0,但是这样会丢失分子的1,

    所以先把36个36分之1从求和中拿出来。

    得到最后的公式就是

    dp[i][j] = E{ (dp[i-t][j-k]) * 1 / 36}  + 1;

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    
    double p = 1.0/36;
    double dp[1000+10][1000+10];
    
    
    int main(int argc, char const *argv[])
    {
    
        //DP过程
        int n;
        cin>>n;
        //以此更新每个点
        for (int i = 1; i <=n; ++i){
            for (int j=1; j <=n; ++j){
                dp[i][j] = 0.0;
                //从36个小棋盘中跨越出来 
                for (int dx = 1; dx <=6 ; ++dx){
                        for (int dy=1; dy <= 6; ++dy){
                            if(i-dx>=1 and j-dy>=1)
                                dp[i][j] += dp[i-dx][j-dy]/36;
                        }
                    }
                dp[i][j]+=1.0;
            }
        }
        printf("%.2f
    ", dp[n][n] );
    
        return 0;
    }
  • 相关阅读:
    ACL-包过滤技术
    基于Openwrt虚拟路由MAC地址
    openwrt串口控制台+联网
    HSRP
    LeetCode37题解(yield生成器提高速度)
    递归+HashMap套路(可以对付可降解问题)
    python实现24点游戏(地球上最短的24点游戏代码?)
    怎么把pygame的过程录制到mp4
    python排列组合算法
    递归和迭代,以及汉诺塔,采用迭代法不容易实现的说明
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1390.html
Copyright © 2020-2023  润新知