Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2415 | Accepted: 1576 |
Description
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
Output
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
Source
算法思想:
题目大意:每个人允许猜 G 次,有 L 生命线。
猜低或猜高了,耗费一次猜得机会,猜高了,还会浪费一生命线。
// DP(动态规划)问题,一般用递推来做,不用递归,递归太费时间
// 先从搜索考虑。设f(guss,life)表示有guss次机会,life条生命线时可以猜到的最大价格范围N。
// 那么,f(guss,life)应该由3种情况组成组成:
1.猜低了,用剩下的机会还能猜出f(guss-1,life)范围的价格;
2.猜得正好,1次猜出价格
3.猜高了,用剩下的机会还能猜出f(guss-1,life-1)范围的价格。
拼起来,就有f(guss,life) = f(guss-1,life) + f(guss-1,life-1) + 1。
// 然后考虑一下边界情况:当g=0时,游戏结束了,所以f(0,life)=0;
// 当life=0时,价格不能再猜高了,只能往下再摸索guss次,所以f(guss,0)=guss。
// 这样就可以用搜索来解决这个题了。再转成记忆化搜索就行了。
// 也可以观察出阶段,自底向上推。
for example:
其中guss代表行,life代表列
执行完for循环的数组:
由于数组太大,我们暂时只给出4列:
当执行完for循环后,dp二维数组状态为:
0 0 0 0 -------------------f(0,life) = 0,符合这个规律,而第一列符合f(guss,0) = guss
1 1 1 1
2 3 3 3
3 6 7 7
f(3,0) = 3;
f(3,1) = 6;
比如:
f(3,1) = f(2,1) + f(2,0) + 1
= [f(1,1)+f(1,0)+1] + 2 + 1
= [[f(0,1)+f(0,0)+1] + 1 + 1] + 2 + 1
= 0 + 0 + 1 + 1 + 1 + 2 +1
= 6
代码如下:
/***********************************************************************
Copyright (c) 2015,wangzp
All rights no reserved.
Name: 《One Person》In PEKING UNIVERSITY ACM
ID: PROBLEM 1243
问题简述: 典型递归问题,用一个相同的算法去解决子问题,并最终有一个返回的值出口作为结束条件。
Date: Sep 02, 2015
***********************************************************************/
#include"stdio.h"
#include
int main(void)
{
int dp[31][31];
int n_guss,n_life,i,j,temp = 1;
memset(dp,0,sizeof(dp));
for(i = 0;i < 31;++i)
{
dp[ i ][ 0 ] = i;//f(guss,0)=guss,把0个life的行赋值为0,1,2....
}
for(i = 1;i < 31;++i)
{
for(j = 1;j <= i;++j)
{
dp[i ][j] = dp[i - 1][j] + dp[i - 1][j - 1] + 1;
}
while(j < 31)
{
dp[i][j] = dp[i][i];
j++;
}
}
while(scanf("%d %d",&n_guss,&n_life),(n_guss != 0)|| (n_life != 0))
{
printf("Case %d: %d\n",temp++,dp[n_guss][n_life]);
}
return 0;
}