DP--划分问题(掷骰子)
来源:互联网 发布:飞凡软件 编辑:程序博客网 时间:2024/06/06 08:48
要考虑重复情况,例:2个骰子,3个面,1,1,2和2,1,1是一种情况
对于这种情形 我们一般进行排序处理 把所有情况所对应的数从小到大排序
a1<=a2<=a3<=...<=an。
比如1,1,2和2,1,1就相当于1,1,2了
再比如 3,1,2 2,3,1 都相当于1,2,3
这样每种情况都与一个序列一一对应不是吗?
方法一:
和划分问题一类似,考虑动态规划方程
第一个骰子为1时,剩下的骰子有p 个面选择,f(n-1,p)
第一个骰子为2时,剩下的骰子有p-2个面选择,f(n-1,p-1)
……
第一个骰子为p时,剩下的骰子有1 个面选择,f(n-1,1)
所以得到f(n,p)=f(n-1,p)+f(n-1,p-2)+……+f(n-1,1)
由上式可以推出f(n,p-1)=f(n-1,p-2)+f(n-1,p-3)+……+f(n-1,1)
两式联立得递推公式 f(n,p)=f(n-1,p)+f(n,p-1)
当n==1时,f(n,p)=p;当p==1时,f(n,p)==1。
//DP数组记忆化int DP(int n,int p){ if(n==1)return p; else if(p==1) return 1; int dp[n+1][p+1]={1},i,j; for(i=1;i<=n;i++) for(j=1;j<=p;j++) { if(i==1) dp[i][j]=j; else if(j==1) dp[i][j]=1; else dp[i][j]=dp[i-1][j]+dp[i][j-1]; } return dp[n][p];}//递归int f(int n,int p){ if(n==1) return p; else if(p==1) return 1; else return f(n,p-1)+f(n-1,p);}
方法二:
以p个面分别出现的次数为参照,n个骰子,每个骰子有p个面 那么我们只要知道这p个面 每个面出现了多少次,依据上述的排序规则 这个序列就确定了
然后就转化成了一个方程
x1+x2+x3+...xp=n 有多少组非负整数解
(xi代表第i个面出现了多少次)
对于这个方程 我们令ai=xi+1
则x1+x2+x3+...xp=n的非负数解与方程 a1+a2+a3+...ap=n+p的正数解一一对应
a1+a2+a3+...ap=n+p 这个方程的正数有多少组解呢? 答案是C(n+p-1,p-1)种
因为可以看成是有n+p个1 然后中间插入p-1个板子 隔板法求得方程的解数
所以一次掷n个骰子,每个骰子有p个面 有C(n+p-1,p-1)种情况.
//计算组合数C(n,m)int C(int n,int m){ if(m>n/2) m=n-m; double result=1; int i=n,j=m,t; while(i>=n-m+1||j>=1) { if(i>=n-m+1) { result*=(i*1.0); i--; } if(j>=1) { result/=(j*1.0); j--; } } return (int)result;}int Formula(int n,int p) // C(n+p-1,p-1){ return C(n+p-1,p-1);}
- DP--划分问题(掷骰子)
- 划分问题(dp)
- jzoj 3072 掷骰子 (概率dp)
- 【NOIP 模拟题】掷骰子(dp)
- DP--划分问题(1)
- 概率dp题,掷骰子
- 掷骰子问题
- 掷骰子问题
- nyoj 571 整数划分问题(dp)
- dp-整数划分问题(理论分析)
- dp-整数划分问题(理论分析)
- 复杂的整数划分问题(dp)
- 题解:整数划分问题(DP)
- 划分数问题 DP
- 整数划分问题 【DP】
- 整数划分问题 DP
- dp-整数划分问题
- 一类DP问题的分析(划分DP)
- Qt:程序桌面图标生成
- U-boot主Makefile分析
- Windows 任务管理器中的几个内存概念
- 通信的五层模型
- 序列化工具SerializeUtils
- DP--划分问题(掷骰子)
- JS编程小常识很有用
- BSP-Apache HAMA-Graph运行(1)
- 《AngularJs实战》笔记
- C语言文件操作实现的记账功能的控制台程序
- 创建Fedora LiveCD
- ImageView变成灰色
- 在centos7中使用service iptables stop 显示not loaded
- 漫话中国古代史 —— 古人的 money