LeetCode808。分割スープ(動的プログラミング)

記事ディレクトリ

1.タイトル

スープには、AとBの2種類があります。最初は、スープの種類ごとにN mlあります。4つの割り当て操作があります。

  • スープA 100mlとスープB 0mlを用意します。
  • スープA 75mlとスープB 25mlを用意します。
  • 50mlスープAと50mlスープBを用意します。
  • スープA 25mlとスープB 75mlを用意します。

スープを誰かに割り当てると、スープはなくなります。
各ラウンドでは、0.25の同じ確率 4つの操作からの選択肢割り当てます。
スープの残量が少ない場合は、できる限り割り当てます。
両方のタイプのスープが出たら、操作を停止します。

なお、スープB100mlを先に出す操作はありません。

返される必要がある値:スープAが最初に割り当てられる確率+スープAとスープB が同時に割り当てられる確率/ 2。

示例:
输入: N = 50
输出: 0.625
解释:
如果我们选择前两个操作,A将首先变为空。
对于第三个操作,A和B会同时变为空。
对于第四个操作,B将首先变为空。
所以A变为空的总概率加上A和B同时变为空的概率的一半是 
0.25 *(1 + 1 + 0.5 + 0)= 0.625。

注释:
0 <= N <= 10^9。
返回值在 10^-6 的范围将被认为是正确的。

出典:LeetCodeリンク:https://leetcode-cn.com/problems/soup-servings
著作権はLeetCode が所有しています商用転載については、正式な許可書にご連絡ください。非商用転載については、出典を明記してください。

2.問題解決

  • 動的プログラミング、注を参照
  • Nは非常に大きいため、マップストレージの状態が使用され、Aが最初に消費される可能性が高いことを考慮すると、N> = 4800を計算すると、確率誤差は1e-6未満になります。
class Solution {
    
    
public:
    double soupServings(int N) {
    
    
    	unordered_map<int,unordered_map<int,double>> dp, temp;
        if(N >= 4800) return 1;//经过计算 N=4800时,prob = 0.99999,误差小于1e-6
    	dp[N][N] = 1.0;
    	double prob = 0.0, p;
    	vector<vector<int>> delta = {
    
    {
    
    100,0},{
    
    75,25},{
    
    50,50},{
    
    25,75}};
    	int A, B, nA, nB, i;
        while(!dp.empty())
        {
    
    
            for(auto& item1 : dp)
            {
    
    	
                A = item1.first;
                for(auto& item2 : item1.second)
                {
    
    
                    B = item2.first;
                    p = item2.second;
                    if(A == 0)//A喝完了
                    {
    
    
                        if(B == 0)//AB同时喝完
                            prob += p/2.0;
                        else if(B > 0)//A先喝完
                            prob += p;
                    }
                    else//A没完
                    {
    
    
                        if(B == 0)//B先喝完,不在答案考虑范围内
                            continue;
                        for(i = 0; i < 4; i++)//4种情况
                        {
    
    
                            nA = max(0, A-delta[i][0]);//不够,直接全部喝完,为0
                            nB = max(0, B-delta[i][1]);
                            temp[nA][nB] += p*0.25;
                        }
                    }
                }
            }
            dp.swap(temp);//更新dp
            temp.clear();
        }
    	return prob;
    }
};

8 ms 7.6 MB


私のCSDN ブログアドレスhttps://michael.blog.csdn.net/

QRコードを長押しまたはスキャンして、私の公式アカウント(Michael Amin)をフォローし、一緒に来て、学び、一緒に進歩してください!
マイケル・アミン

おすすめ

転載: blog.csdn.net/qq_21201267/article/details/108636952