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)をフォローし、一緒に来て、学び、一緒に進歩してください!