首页 > ACM题库 > HDU-杭电 > HDU 3326-Cover Up[解题报告]HOJ
2014
03-16

HDU 3326-Cover Up[解题报告]HOJ

Cover Up

问题描述 :

“The Price is Right” is a popular game show where contestants play various games to win fabulous prizes. One of the games played on the show is called “Cover Up” whose object is to guess a 5-digit number (actually, the price of a new car). In the actual game, contestants are given two numbers to choose from for the first digit, three numbers to choose from for the second digit, and so on. A contestant selects one number for each digit (from the set of yet unpicked numbers for that digit) and then is told which ones are correct; if at least one is correct, the player is allowed to guess again for all incorrect digits. The contestant keeps guessing as long as they keep getting at least one new digit correct. The game ends when either all the digits are correct (a win for the contestant) or after a turn when no new digit is guessed correctly (a loss).

Typically this game is not sheer luck. For example, suppose you had the following five possibilities for the last digit: 1, 3, 5, 8 and 9. Many car prices end with either a 5 or a 9, so you might have, say, a 70% chance that one of these two numbers is correct; this breaks down to a 35% chance for either the 5 or the 9 and a 10% chance for each of the other three digits. Now say you pick the 5 and it’s wrong, but some other guess you made was right so you still get to play. With this additional information the probabilities for the remaining 4 numbers change: the probability for the 9 is now close to around 54%, while each of the other three numbers now has a little over a 15% chance. (We’ll let you figure out how we got these values). We’ll call the 5 and the 9 in the original group the known candidates, and typically there are known candidates in other columns as well. For example, if the two numbers for the first (high order) digit are 1 and 9, the contestant can be 100% sure that the 1 is the correct digit (there aren’t too many $90,000 cars to be given away).

For this problem, you are to determine the probability of winning the game if an optimal strategy for picking the numbers (based on probabilities such as those described above) is used.

输入:

Each test case will consist of two lines. The first will be n, the number of digits in the number to be guessed. The maximum value of n will be 5. The second line will contain n triplets of numbers of the form m l p where m is the number of choices for a digit, l is the number of known candidates, and p is the probability that one of the known candidates is correct. In all cases 0 ≤ l < m ≤ 10 and 0.0 ≤ p ≤ 1.0. Whenever l = 0 (i.e., when there are no known candidates) p will always be 0.0. A line containing a single 0 will terminate the input.

输出:

Each test case will consist of two lines. The first will be n, the number of digits in the number to be guessed. The maximum value of n will be 5. The second line will contain n triplets of numbers of the form m l p where m is the number of choices for a digit, l is the number of known candidates, and p is the probability that one of the known candidates is correct. In all cases 0 ≤ l < m ≤ 10 and 0.0 ≤ p ≤ 1.0. Whenever l = 0 (i.e., when there are no known candidates) p will always be 0.0. A line containing a single 0 will terminate the input.

样例输入:

2
3 1 0.8 2 0 0.0
2
3 2 0.8 2 0 0.0
2
3 2 0.82 2 1 0.57
3
4 1 1.0 3 0 0.0 10 1 1.0
0

样例输出:

0.85
0.6
0.644
1

#include<cstdio> 
#include<iostream>
#include<cstring>
using namespace std;
int n,m[5],l[5],len;
double p[5],dp[6][3125][32];
bool f[6][3125][32];
char ans[100];
double solve(int g,int r,int mask)
{
	if(mask==0) return 1.0;
	if(f[g][r][mask]) return dp[g][r][mask];
	int a[5],c=r;
	double b[2][5],t1,t2;
	for(int i=n-1;i>=0;--i)
	{
		a[i]=c%5;
		c/=5;
	}
	for(int i=0;i<n;++i)
	{
		if(l[i]) t1=p[i]/l[i]*(l[i]-a[i]);
		else t1=0.0;
		t2=(1-p[i])/(m[i]-l[i])*(m[i]-l[i]-g+a[i]); 
		if(t1+t2<1e-8) b[0][i]=b[1][i]=0.0;
		else
		{
			b[0][i]=(1-p[i])/(m[i]-l[i])/(t1+t2);
			b[1][i]=p[i]/l[i]/(t1+t2);
		}
	}
	dp[g][r][mask]=0.0;
	for(int i=mask;;i=((i-1)&mask))
	{
		double tmp=0.0;
		int choose[5],chs=0;
		for(int j=0;j<n;++j)
		{
			if(i&(1<<j)) choose[j]=1;
			else choose[j]=0;
			if((mask&(1<<j))&&choose[j]+a[j]>l[j]) goto fuck;
			if((mask&(1<<j))&&choose[j]==0&&m[j]-l[j]-g+a[j]<=0) goto fuck;
			chs=chs*5+choose[j]+a[j];
		}
		for(int j=mask;j;j=((j-1)&mask))
		{
			double pp=1.0;
			for(int k=0;k<n;++k)
				if(j&(1<<k)) pp*=b[choose[k]][k];
				else if(mask&(1<<k)) pp*=1-b[choose[k]][k];
			tmp+=pp*solve(g+1,chs,mask-j);
		}
		dp[g][r][mask]=max(dp[g][r][mask],tmp);
		fuck:if(i==0) break;
	}
	f[g][r][mask]=1;
	return dp[g][r][mask];
}
int main()
{
	while(scanf("%d",&n)&&n)
	{
		for(int i=0;i<n;++i) scanf("%d%d%lf",m+i,l+i,p+i);
		memset(f,0,sizeof(f));
		memset(ans,0,sizeof(ans));
		sprintf(ans,"%.3lf",solve(0,0,(1<<n)-1));
		len=strlen(ans);
		while(ans[len-1]=='0')
			ans[--len]='\0';
		if(ans[len-1]=='.') ans[len-1]='\0';
		printf("%s\n",ans);
	}
}