[explanation] Uva10529 dumbbones dominoes
meaning of the title
You try to line up some dominoes and push them down. But if you accidentally knock down the newly placed dominoes when you put them, it will knock down all the adjacent strings of dominoes, and your work will be partially destroyed.
For example, you've set your dominoes as DD__ DxDDD_ The shape (side view) of D (where d stands for dominoes, underline and x Stand for empty spaces where dominoes have not been placed), and you want to put another dominoes in the position of x. It may knock down one dominoes on the left or three dominoes on the right, and you will have to rearrange them.
Give the number of dominoes you want to put, and the probability that it will fall to the left and right when you put dominoes (each dominoes is the same).
In order to minimize the number of dominoes expected to be placed, you can use a specific placement order. Find the minimum number of dominoes expected to be placed.
Algorithm 1
Probability + optimal solution, interval DP can be considered
Consider an interval. Enumerate the positions of the last dominoes placed in this interval, and divide the original interval into left and right sub intervals.
Let the expected minimum placement times of the original section be \ (E \), the left section be \ (E_1 \), and the right section be \ (E_2 \). At this time, the last domino has not been put on, so the position of this vacancy is \ (x \)
It is known that the probability of each domino falling to the left is \ (P_l \) and to the right is \ (P_r \)
If you look at the dominoes \ (x \) alone, the probability that it will not fall is \ (1-P_l-P_r \), then the expected number of times it will not fall is \ (\ frac1{1-P_l-P_r} \)
Note that in this number: the last one does not fall, some of the previous ones are left and some are right. Because the probability to the left is \ (P_l \), the number of times to the left is \ (\ frac1{1-P_l-P_r}\times P_l \). Because every time it reverses to the left, the left section must be rearranged. It takes \ (E_1 \) to place the left section once, so the left section should be placed \ (\ frac{P_l}{1-P_l-P_r}\times E_1 \) times in total. Similarly, a total of \ (\ frac{P_r}{1-P_l-P_r}\times E_2 \) times should be placed in the right section.
In addition, before placing \ (x \), the left and right sections need to be placed once, with a total of \ (E_1+E_2 \).
Finally, the state transition equation is
So we easily wrote the following lump
int n; double pl, pr;//Probability of falling left and right double f[N][N];//dp array (memory search) double dfs(int l, int r) {//Left and right end points of interval double &E = f[l][r];//It is convenient and fast to use references if (E > eps) return E;//Memorization if (l > r) return E = 0.0;//boundary if (l == r) return E = 1.0/(1.0-pl-pr);//Just one E = inf;//Let's start with a maximum for (int i=l; i<=r; ++i) {//Enumerate the last placement i double E1 = dfs(l, i-1);//Placement times of left section double E2 = dfs(i+1, r);//Right interval E = std::min( E, E1 + E2 + 1.0/(1.0-pl-pr) + pl*E1/(1.0-pl-pr) + pr*E2/(1.0-pl-pr)//The equation just now );//The optimal solution is obtained by min } return E; }
Then the glorious T flew to zero
Algorithm 2
The above algorithm is \ (O(n^3) \), of course not. We consider dimensionality reduction
Because each card is as like as two peas, and the same is true for all the same lengths of intervals. Their E\ is the same.
If the state is reset to the interval length, only the intervals with different lengths need to be transferred, and the state transfer equation remains unchanged
Obtain positive solution
#include <cstdio> #include <iostream> using namespace std; #define N 1030 const double eps = 1e-8; const double inf = 1e20; double pl, pr;//Probability of falling left and right double f[N]; double dfs(int n) {//Interval with length n double &E = f[n], E1, E2;//Or reference if (E > -0.5) return E;//Let f[0]=0.0 and f[1]=1.0/(1.0-pl-pr) transfer naturally E = inf; for (int i=1; i<=n; ++i) { E1 = dfs(i-1), E2 = dfs(n-i);//Left and right answers E = min( E, E1 + E2 + f[1] + pl*E1*f[1] + pr*E2*f[1] ); } return E; } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr);//Turn off stream synchronization while (true) { int n; cin >> n; if (!n) break; cin >> pl >> pr; for (int i=2; i<=n; ++i) f[i] = -1.0;//Pay attention to details f[1] = 1.0 / (1.0 - pl - pr);//Meanwhile, f[0]=0.0 printf("%.2f\n", dfs(n)); } return 0; }