GCJ 2008 APAC local onsites C(Millionaire) (dp+離散化)

題意:

 

剛開始持有x元錢

將進行M輪賭博

每輪贏得概率爲P

贏則賭注翻倍,輸則賭注全無

問最優策略下賺得1000000元錢(或以上)的概率。

 

思路:

 

搜索:

 

double chance(int cengshu, int money)

{

         if(cengshu== M )

{

         if(money>=1000000)

                   return 1;

         if(money>=500000)

                   return 0.5;

         return 0;

}

 

double  chance_now = 0.0;

for(int I = 0; i<= money; i++)

         chance_now=min(chance_now,P*chance(cengshu+1,money+i)+(1-P)*chance(cengshu+1,money-i));

 

returnchance_now;

}

 

定義dp[i][j]爲初始賭資2^j元經過i輪賭博賭資擴大到2^M元的概率

 

令x = min(j, 2^M)

 

則dp[i+1][j] = max{P*dp[i][j+y] + (1-P)*dp[i][j-y]}   (0<=y<=x)

發現在轉移過程之中僅僅需要上層i的值,所以只用兩層數組記錄即可。

 

P.S.注意考慮錢數與概率的對應關係,這是離散化處理的保證

#include <stdio.h>
#include <algorithm>
#include <string.h>
#define LL long long

using namespace std;

double dp[2][1<<15 + 1];

int main()
{
	int M, X;
	double P;
	while(scanf("%d %lf %d", &M, &P, &X)==3)
	{
		memset(dp, 0, sizeof(dp));
		int n = 1<<M;
		double *fomer = dp[0];
		double *later = dp[1];
		fomer[n] = 1;

		for (int i = 0; i < M; ++i)
		{
			for (int j = 0; j <= n; ++j)
			{
				int temp = min(j, n - j);
				double t = 0.0;
				for (int k = 0; k <= temp; ++k)
				{
					t = max(t, P*fomer[j+k]+(1-P)*fomer[j-k]);
				}
				later[j] = t;
			}
			swap(fomer, later);
		}
		int i = (LL)X*n / 1000000;
		printf("%0.6f\n", fomer[i]);
	}
}


發佈了30 篇原創文章 · 獲贊 0 · 訪問量 9156
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章