http://blog.csdn.net/joylnwang/article/details/6769160

先给大家看看大神写的扔鸡蛋问题。所有的原理,DP实现都在,不赘述。大家好好学习,天天向上。

我想分享的是:

第一次扔地点的最佳地点的递归找法:(自己的测试都过了,希望大家都来查错;想按照大神的意思,找出所有的分界点,即找出扔各个鸡蛋的碎或没碎太困难啦,啥时候想到再分享给大家)


贴代码解释:

#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;

int steps=0;

const int maxn=100;
const int maxm=100;
int drop[maxn][maxm];
int Max;
int before;

int Dropping(int n,int m)//跑一次记忆化DP,找到最优值,保存各个中间过程 
{
	if (n==1) return drop[n][m]=m;
	if (n>=m) return drop[n][m]=pow(2,m)-1;
	if (drop[n-1][m-1]==0) Dropping(n-1,m-1);
	if (drop[n][m-1]==0) Dropping(n,m-1);
	return drop[n][m]=Dropping(n-1,m-1)+1+Dropping(n,m-1);
}

int findans(int n,int m)//找出当前最大值的第一个测试点!!
{
	int ans;
	if (n==1)//处理第一种情况
	{
		for(int i=before+1;i<=Max;i++)
				printf("%d%c",i,i==Max?'\n':' ');
	}
	else if (n<m)//处理递归分解的情况 
	{
		ans=Max-drop[n][m-1];//用Max去减是因为我要算的是前面的累加和是多少 
		before=ans; //before记录的是上一次的分点在哪儿
		printf("%d",ans);
		if (Max-ans)//如果ans==Max了,说明已经把鸡蛋扔到顶层了 
		{
			printf(" ");findans(n,m-1);
		}
		else printf("\n");
	}
	else//处理n=m时候的情况,每次往后找,相当于区间二分 
	{
		if (n>0)
		{
			ans=before+pow(2,m-1);//before记录的是上一次的分点在哪儿 
			before=ans;
			printf("%d",ans);
			if (Max-ans)
			{
				printf(" ");
				findans(n-1,m-1);
			}
			else printf("\n");
		}
	}
}

int main()
{
	int n,m;
	//n=2,m=8;
	memset(drop,0,sizeof(drop));
	scanf("%d%d",&n,&m);
	printf("%d\n",Dropping(n,m));
	Max=drop[n][m];
	before=0;
	findans(n,m);
	return 0;
}
/*
	这其实只例举了正好D[n,m]的情况,
	其实,这个第一次扔鸡蛋的分案完全适用于:D[n,m-1]<k<=D[n,m]的所有情况
	原因解释:
	无非就是把后面的几个完整区间压缩小了而已啊!
*/