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]的所有情况
原因解释:
无非就是把后面的几个完整区间压缩小了而已啊!
*/