首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

POJ 1322 Chocolate:概率 DP 求剩餘巧克力分布

     編輯:C++ 入門

問題描述

c 種顏色巧克力,每次隨機取一個。若與手中已有顏色相同,吃掉(配對消失)。取 n 個後剩 m 個的概率。m+n 為奇則概率 0。

DP 狀態定義

dp[i][j]:取了 i 個後,手中剩 j 個不同顏色巧克力的概率。

轉移方程

dp[i][0] = dp[i-1][1] / c
dp[i][c] = dp[i-1][c-1] / c
dp[i][j] = dp[i-1][j-1] * (c-j+1)/c + dp[i-1][j+1] * (j+1)/c  (1 ≤ j < c)

解釋:

  • 從 j-1 狀態轉移:抽到新顏色,概率 (c-(j-1))/c
  • 從 j+1 狀態轉移:抽到已有顏色配對消失,概率 (j+1)/c

代碼實現

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;

double dp[1010][1010];

int main() {
    int c, n, m;
    while (~scanf("%d", &c), c) {
        scanf("%d%d", &n, &m);
        if (m > c || m > n || (n+m)%2) { printf("0.000\n"); continue; }
        if (n > 1000) n = 1000 + n%2; // 穩態截斷
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            dp[i][0] = dp[i-1][1] / c;
            dp[i][c] = dp[i-1][c-1] / c;
            for (int j = 1; j < c; ++j)
                dp[i][j] = dp[i-1][j-1]*(c-j+1)/c + dp[i-1][j+1]*(j+1)/c;
        }
        printf("%.3lf\n", dp[n][m]);
    }
    return 0;
}

優化技巧

  • n > 1000 時,概率分布趨於穩態,截斷 n 為 1000 或 1001(保持奇偶性)
  • 邊界 j=0 和 j=c 單獨處理
  • 輸出保留 3 位小數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved