/******************************************************************************
ペアマッチ(新婚さんいらっしゃい!)で獲得できる商品数の期待値を求める。
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define N0 0 /* 基準値 */
#define N1 1 /* 単位の数 */
#define N2 2 /* ペアの数 */
#define N4 4 /* 状態の数 */
#define N8 8 /* 賞品の数 */
#define N9 9 /* N8 + N1 */
#define SENKO 0 /* 先攻 */
#define KOKO 1 /* 後攻 */
double dShohin[9][9]; /* 先攻、後攻がそれぞれ獲得した賞品数ごとの確率 */
static int nZobun[4][N2] = {N1,N0 , N0,N1 , N1,N0 , N0,N1};
/* 状態ごとの獲得賞品増分 */
/******************************************************************************
機能:パネルをオープンして、次に進める。
引数:
1 (I) nMikai 2枚とも場所が不明な賞品の数
2 (I) nKataho 1枚の場所が判明している賞品の数
3 (I) nHanmei 2枚とも場所が判明しているが、まだ獲得されていない賞品の数
4 (I) nSenko 先攻ペアが獲得した賞品の数
5 (I) nKoko 後攻ペアが獲得した賞品の数
6 (I) prob その状態に至る確率
7 (I) status 状態(0.先攻新郎、1.後攻新郎、2.先攻新婦、3.後攻新婦)
戻り値:なし
******************************************************************************/
void junban(int nMikai , int nKataho , int nHanmei , int nSenko , int nKoko ,
double prob , int status)
{
double t1 , t2; /* 次の状態の確率計算用一時変数 */
double nextProb; /* 次の状態の確率 */
if(status == N4 || nSenko + nKoko == N8) {
dShohin[nSenko][nKoko] += prob;
return;
}
t1 = 2.0 * (double)nMikai + (double)nKataho;
t2 = t1 * (t1 - 1.0);
if(nHanmei == N0) {
if(t1 != 0.0) {
/* 1枚目で、片方が判明している賞品をオープンして獲得 */
nextProb = prob * (double)nKataho / t1;
junban(nMikai , nKataho - 1 , N0 , nSenko + nZobun[status][SENKO] ,
nKoko + nZobun[status][KOKO] , nextProb , status);
}
if(t2 != 0.0) {
/* 1枚目、2枚目で同じ賞品をオープンして獲得 */
nextProb = prob * 2.0 * (double)nMikai / t2;
junban(nMikai - 1 , nKataho , N0 , nSenko + nZobun[status][SENKO] ,
nKoko + nZobun[status][KOKO] , nextProb , status);
/* 1枚目、2枚目とも初めての賞品 */
nextProb = prob * 2.0 * (double)nMikai *
(2.0 * (double)nMikai - 2.0) / t2;
junban(nMikai - 2 , nKataho + 2 , N0 , nSenko, nKoko ,
nextProb , status + N1);
/* 1枚目が初めての賞品、2枚目が片方が判明している賞品 */
nextProb = prob * 2.0 * (double)nMikai * (double)nKataho / t2;
junban(nMikai - 1 , nKataho , N1 , nSenko , nKoko , nextProb ,
status + N1);
}
}
else {
/* 2枚とも判明している賞品を獲得 */
junban(nMikai , nKataho , N0 , nSenko + nZobun[status][SENKO] ,
nKoko + nZobun[status][KOKO] , prob , status);
}
}
/******************************************************************************
機能:メイン
引数:なし
戻り値:EXIT_SUCCESS
******************************************************************************/
int main(void)
{
int i , j; /* ループ制御変数 */
double sProb[N9][N2]; /* 獲得数ごとの確率 */
static double dKitai[N2] = {(double)N0 , (double)N0}; /* 期待値 */
for(i = N0 ; i < N9 ; i++) {
sProb[i][SENKO] = sProb[i][KOKO] = (double)N0;
for(j = N0 ; j < N9 ; j++) dShohin[i][j] = (double)N0;
}
junban(8 , N0 , N0 , N0 , N0 , 1.0 , N0);
for(i = N0 ; i < N9 ; i++) {
for(j = N0 ; j < N9 ; j++) {
sProb[i][SENKO] += dShohin[i][j];
sProb[j][KOKO] += dShohin[i][j];
dKitai[SENKO] += ((double)i * dShohin[i][j]);
dKitai[KOKO] += ((double)j * dShohin[i][j]);
}
}
for(i = N0 ; i < N9 ; i++) {
printf("%d %8.5lf %8.5lf\n" , i , sProb[i][SENKO] , sProb[i][KOKO]);
}
printf("期待値 先攻:%6.3lf 後攻:%6.3lf\n" , dKitai[SENKO] , dKitai[KOKO]);
return(EXIT_SUCCESS);
}
|