Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
借助大牛的记忆搜索(DP),改了改代码,不过我把算法和过程分析的很清楚了,可以满足不清楚的童鞋了/* 算法思想: 题目大意:每个人允许猜 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 --------------------------code-------------------- #include"stdio.h" #include <string.h> 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; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator