SRM 504.5(2-1000pt)

时间:2023-03-09 03:52:12
SRM 504.5(2-1000pt)

DIV2 1000pt

题意:一群人排队,每次操作由要骰子决定,只要没有人中奖,游戏就不结束。若摇骰子摇出4,则队列第一个人中奖;否则,若摇的是奇数,则第一个人排队到队伍末尾去;否则,第一个人出局。若游戏途中,队列只剩一个人,则直接中奖。若摇了k次骰子仍然没人中奖,则此时队列第一个人自动获奖,游戏结束。给出k,问队列初始时为n个人,此时排在第m个的人中奖的概率有多大。n, m, k <= 10。

解法:普通的概率dp。将题中的k记为num。

   法一:设d[i][j][k]表示当前状态为摇了i次骰子,队列共有j人,排在第k个的中奖的概率。具体状态转移方程见代码,很简单。

   法二:设d[i][j][k]表示由初始状态变成摇了i次骰子后,队列有j个人,初始时排在第m个的人现在排在第k个的概率。状态转移方程同见方程。

tag:概率dp

法一:

 // BEGIN CUT HERE
/*
* Author: plum rain
* score :
*/
/* */
// END CUT HERE
#line 11 "TheTicketsDivTwo.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <queue>
#include <bitset>
#include <list>
#include <string>
#include <utility>
#include <map>
#include <ctime>
#include <stack> using namespace std; #define CLR(x) memset(x, 0, sizeof(x))
#define CLR1(x) memset(x, -1, sizeof(x))
#define PB push_back
#define SZ(v) ((int)(v).size())
#define zero(x) (((x)>0?(x):-(x))<eps)
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl
#define CINBEQUICKER std::ios::sync_with_stdio(false) typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long int64; const double eps = 1e-;
const double PI = atan(1.0)*;
const int maxint = ; double d[][][]; class TheTicketsDivTwo
{
public:
double find(int n, int m, int num){
double t1 = (double) / (double), t2 = (double) / (double);
CLR (d);
for (int i = ; i <= n; ++ i)
d[num][i][] = ; for (int i = num-; i >= ; -- i)
for (int j = ; j <= n; ++ j)
for (int k = ; k <= j; ++ k){
if (j == ) d[i][j][k] = ;
else if (k == ) d[i][j][k] = d[i+][j][j]*0.5 + t2;
else d[i][j][k] = d[i+][j][k-]*0.5 + d[i+][j-][k-]*t1;
}
return d[][n][m];
} // BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -) || (Case == )) test_case_0(); if ((Case == -) || (Case == )) test_case_1(); if ((Case == -) || (Case == )) test_case_2(); if ((Case == -) || (Case == )) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.16666666666666666; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_1() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.5833333333333334; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_2() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.0; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_3() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.25264033564814814; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); } // END CUT HERE }; // BEGIN CUT HERE
int main()
{
// freopen( "a.out" , "w" , stdout );
TheTicketsDivTwo ___test;
___test.run_test(-);
return ;
}
// END CUT HERE

法二:

 // BEGIN CUT HERE
/*
* Author: plum rain
* score :
*/
/* */
// END CUT HERE
#line 11 "TheTicketsDivTwo.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <queue>
#include <bitset>
#include <list>
#include <string>
#include <utility>
#include <map>
#include <ctime>
#include <stack> using namespace std; #define CLR(x) memset(x, 0, sizeof(x))
#define CLR1(x) memset(x, -1, sizeof(x))
#define PB push_back
#define SZ(v) ((int)(v).size())
#define zero(x) (((x)>0?(x):-(x))<eps)
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl
#define CINBEQUICKER std::ios::sync_with_stdio(false) typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long int64; const double eps = 1e-;
const double PI = atan(1.0)*;
const int maxint = ; double d[][][]; class TheTicketsDivTwo
{
public:
double find(int n, int m, int num){
double t1 = (double) / (double), t2 = (double) / (double);
CLR (d);
d[][n][m] = 1.0;
for (int i = ; i <= num; ++ i)
for (int j = ; j <= n; ++ j)
for (int k = ; k <=j; ++ k){
if (j == k){
if (j == ) d[i][][] = d[i-][j+][j+] * t1;
else d[i][j][k] = d[i-][j][] * 0.5 + d[i-][j+][j+] * t1;
}
else{
d[i][j][k] = d[i-][j][k+] * 0.5;
if (j < n) d[i][j][k] += d[i-][j+][k+] * t1;
}
} double ans = ;
for (int i = ; i < num; ++ i)
for (int j = ; j <= n; ++ j)
ans += d[i][j][] * (j == ? : t2);
for (int i = ; i <= n; ++ i)
ans += d[num][i][];
return ans;
} // BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -) || (Case == )) test_case_0(); if ((Case == -) || (Case == )) test_case_1(); if ((Case == -) || (Case == )) test_case_2(); if ((Case == -) || (Case == )) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.16666666666666666; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_1() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.5833333333333334; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_2() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.0; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); }
void test_case_3() { int Arg0 = ; int Arg1 = ; int Arg2 = ; double Arg3 = 0.25264033564814814; verify_case(, Arg3, find(Arg0, Arg1, Arg2)); } // END CUT HERE }; // BEGIN CUT HERE
int main()
{
// freopen( "a.out" , "w" , stdout );
TheTicketsDivTwo ___test;
___test.run_test(-);
return ;
}
// END CUT HERE