Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

借助大牛的记忆搜索(DP),改了改代码,不过我把算法和过程分析的很清楚了,可以满足不清楚的童鞋了

Posted by wzp_moon at 2015-09-02 17:03:54 on Problem 1243
/*
算法思想:
题目大意:每个人允许猜 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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator