扔了一夜的鸡蛋,找出来了第一次扔鸡蛋的最佳地点

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

先给你们看看大神写的扔鸡蛋问题。全部的原理,DP实现都在,不赘述。你们好好学习,每天向上。测试

我想分享的是:spa

第一次扔地点的最佳地点的递归找法:(本身的测试都过了,但愿你们都来查错;想按照大神的意思,找出全部的分界点,即找出扔各个鸡蛋的碎或没碎太困难啦,啥时候想到再分享给你们).net


贴代码解释:code

#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]的全部状况
	缘由解释:
	无非就是把后面的几个完整区间压缩小了而已啊!
*/