http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=503
// 题目大意:每个人允许猜 G 次,有 L 生命线。猜低或猜高了,耗费一次猜得机会,猜高了,还
// 会浪费一生命线。
// dp
// 先从搜索考虑。设f(g,l)表示有g次机会,l条生命线时可以猜到的最大价格范围。
// 那么,f(g,l)应该由三段范围组成:猜低了,用剩下的机会还能猜出f(g-1,l)范围的价格;
// 猜得正好,可以猜出1个价格;猜高了,用剩下的机会还能猜出f(g-1,l-1)范围的价格。
// 拼起来,就有f(g,l)=f(g-1,l)+1+f(g-1,l-1)。
// 然后考虑一下边界情况:当g=0时,游戏结束了,所以f(0,l)=0;
// 当l=0时,价格不能再猜高了,只能往下再摸索g次,所以f(g,0)=g。
// 这样就可以用搜索来解决这个题了。再转成记忆化搜索就行了。
// 也可以观察出阶段,自底向上推。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<bitset> using namespace std; int main() { int dp[ 32 ][ 32 ]; int i , j ; memset( dp , 0 , sizeof( dp ) ) ; for( i = 0 ; i < 32 ; ++i ) dp[ i ][ 0 ] = i ; for( i = 1 ; i < 32 ; ++i ) { for( j = 1 ; j <= i ; ++j ) dp[ i ][ j ] = dp[ i - 1 ][ j ] + dp[ i - 1 ][ j - 1 ] + 1 ; for( ; j < 32 ; ++j ) dp[ i ][ j ] = dp[ i ][ i ] ; } int g , l ; int temp = 1 ; while( cin >> g >> l ) { if( !( g + l ) ) return 0 ; printf("Case %d: %d\n", temp ++ , dp[ g ][ l ] ) ; } }