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