首页 > 代码库 > POJ-1243 One Person (经典级dp

POJ-1243 One Person (经典级dp

One Person
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 2122 Accepted: 1426

Description

In the game show "The Price is Right", a number of players (typically 4) compete to get on stage by guessing the price of an item. The winner is the person whose guess is the closest one not exceeding the actual price. Because of the popularity of the one-person game show "Who Wants to be a Millionaire",the American Contest Management (ACM) would like to introduce a one-person version of the "The Price is Right". In this version, each contestant is allowed G (1 <= G <= 30) guesses and L (0 <= L <= 30)lifelines. The contestant makes a number of guesses for the actual price. After each guess, the contestant is told whether it is correct, too low, or too high. If the guess is correct, the contestant wins. Otherwise,he uses up a guess. Additionally, if his guess is too high, a lifeline is also lost. The contestant loses when all his guesses are used up or if his guess is too high and he has no lifelines left. All prices are positive integers. 
It turns out that for a particular pair of values for G and L, it is possible to obtain a guessing strategy such that if the price is between 1 and N (inclusive) for some N, then the player can guarantee a win.The ACM does not want every contestant to win, so it must ensure that the actual price exceeds N.At the same time, it does not want the game to be too diffcult or there will not be enough winners to attract audience. Thus, it wishes to adjust the values of G and L depending on the actual price. To help them decide the correct values of G and L, the ACM has asked you to solve the following problem.Given G and L, what is the largest value of N such that there is a strategy to win as long as the price is between 1 and N (inclusive)? 

Input

The input consists of a number of cases. Each case is specified by one line containing two integers G and L, separated by one space. The end of input is specified by a line in which G = L = 0. 

Output

For each case, print a line of the form: 
Case c: N 
where c is the case number (starting from 1) and N is the number computed. 

Sample Input

3 0
3 1
10 5
7 7
0 0

Sample Output

Case 1: 3
Case 2: 6
Case 3: 847
Case 4: 127

不得不说,看了题解之后才感受到这题的巧妙。

题目大意:

有一种猜数字的游戏,你有G次机会以及L点生命值,游戏首先给定一个范围1~N,你要来猜在此范围内的一个数字X。你的每次猜测都会告诉你是猜高了还是低了,每次猜测都要损失一次猜测机会(即G--),但如果你猜的值比X高了,那么同时还要损失一点生命值(L--)。

现在主办人面临一个问题:若给定的范围太大,就有很有可能导致参赛者用尽机会和生命值也猜不到这个X;而范围太小的话又降低了趣味性。所以,需要你来帮忙,根据给定的G和L来确定一个尽量大的范围,同时确保该范围内的所有数字都是一定可以被猜到的。


解题思路:


设f(G,L)为有G次机会,L点生命值时最多可猜到多少个数字(注意此处的描述


猜数字我们都知道是要用二分法来猜.首先,要考察G与L间的大小关系:

1)、若L=0,即一次都不可以猜高了,那么保险能猜到的方案就只有1、2、3、4。。。的一个一个往上猜,那么最多能猜到的数字个数也就是G

2)、若L>G,即可以猜高的次数比较多。可事实上,每次猜测都要耗费一点G,那么多出来的生命值也就没什么意义了,所以这种情况与L=G相同,即f(G,G)

3)、若L<=G,那么,就要继续分类考虑。首先进行一次猜测(假设猜的是k),那么可能得到以下三种情况之一:

(1):猜低了。也就是说明正确答案大于k(此处可脑补一条以k为原点的数轴辅助理解),那么接下来的猜测就要相对于k往前(以数轴正方向为前),此时剩余G-1点机会,L点生命,也就是说可以再向前猜出f(G-1,L)个数字。

(2):猜高了。也就是说正确答案小于k,那么接下来就要相对于k向后猜,同理,可以再向后猜出f(G-1,L-1)个数字。

(3):恰好猜到~

总结下,即当L<=G时,f(G,L)=f(G-1,L)+f(G-1,L-1)+1


例如:

有2次机会(先不考虑生命值),就可以猜出1~3中所有数,有3此机会,就可猜出1~7

不过不要把思路局限为只能从1开始。比如有2次机会,也可以猜出5~7范围内给定的某个数,即是说有两次机会时,可以猜出连续的3个数字。那么3次机会时,就可以看作首先猜4,剩下2次机会,可以向前或向后猜3个数字,即范围为1~7;同理,若有三次机会,第一次猜的是0,那么就可以猜到-3~3。


代码:

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

int dp[35][35];

int f(int i,int j)
{
	if(i==0)	return 0;
	if(j==0)	return i;
	if(dp[i][j]>0)	return dp[i][j];

	dp[i][j]=f(i-1,j)+f(i-1,j-1)+1;

	return dp[i][j];
}

int main()
{
	int G,L,cas=0;
	while(cin>>G>>L)
	{
		if(G==0&&L==0)	break;
		++cas;
		memset(dp,0,sizeof(dp));

		if(L==0)
		{
			printf("Case %d: %d\n",cas,G);
			continue;
		}
		if(L>G)	L=G;
		printf("Case %d: %d\n",cas,f(G,L));
	}
	return 0;
}