[solution] uva10529 dumbbones dominoes

[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

\[E=E_1+E_2+\frac1{1-P_l-P_r}+\frac{P_l\times E_1}{1-P_l-P_r}+\frac{P_r\times E_2}{1-P_l-P_r} \]

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(
			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(
			E1 + E2 + f[1] + pl*E1*f[1] + pr*E2*f[1]
	return E;

signed main()
	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;

Posted by pets2soul on Sun, 07 Nov 2021 21:47:30 -0800