DP算法解释

稍微解释下:
BitSet isSolved,isSuit
中的isSolved.get(n,k)表示(n,k)是否已经求解过
isSuit.get(n,k)为true表示n个人可能为k场
简记isSuit.get(n,k)为s[n,k].

n个人能够比k场实际上是问: n能否存在一个分解 xi(xi>0)使得
Sum{xi} =n, Sum{xi*xj: i!=j} =k;
注意到 Sum{xi}*Sum{xi} = Sum{xi*xj}

= Sum{xi*xi} +2 *Sum{xi*xj: i!=j}
又易知 n <=Sum{xi*xi} <= n*n
故可得k的取值范围为: 0<=k <= n*(n-1)/2
因此我们只需判断 k在 [0,n*(n-1)/2]中的取值.

下面我们来推导DP状态转移方程:

假设n存在分解 n = Sum{xi: 1<=i<=L}
使得 k = Sum{xi*xj: 1<=i,j<=L,i!=j}
有: k = Sum{x1*xi: i!=1} +Sum{xi*xj: 2<=i,j<=L,i!=j}
= x1*(n-x1) +Sum{xi*xj:2<=i,j<=L,i!=j}
可以看出: {xi: 2<=i<=L}是 k- x1*(n-x1)的一个满足条件的分解
从而我们有:
s[n,k] = OR{s[n-m,k-m*(n-m)] : 1<=m其中OR表示逻辑或运算.

6.11添加:对offset()方法的说明
对于每一个n,我只需计算s[n,0],s[n,1],....,s[n,n*(n-1)/2]
很容易可以想到可以用一个二维boolean数组来保存s的值:
boolean[][] s =new boolean[MAX+1][]; //用MAX+1是因为把n=0的情形也包含进出了
然后:
s[n] =new boolean[n*(n-1)/2+1]
不过,这里我没有采用boolean数组,而是采用一个BitSet(后面的C代码用的是一个char数组,然后用其每一个bit保存一个值).
BitSet可以看成是一个一维bit数组,但这里我们就要考虑如何将原来的二维boolean数组"拉直"成一维数组了:
显然,我们只要知道s[n]对应的BitSet位置就可以了,这就是offset方法要干的事.
由于s[0]要占1个位,s[1]要占一个位,....,更一般的:
s[m]的取值是0到m*(m-1)/2
因此,s[m]要占 1+m*(m-1)/2 个位 (呵呵,不要把这个1漏了)
这样,我们可以计算s[n]的在BitSet的偏移位置应该是前s[0],...s[n-1]所占位置的总和,也就是:
Sum{1+m*(m-1)/2 : 0<=m<=n-1}
唔,这个求和公式比1加到100要难一些(当然,如果你和我一样是学数学的话就不会觉得难了)
总而言之,求和的结果就是:

引用

offset(n) =Sum{1+m*(m-1)/2 : 0<=m<=n-1}
=n*(n-1)*(n-2)/6 +n

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12467/viewspace-148155/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12467/viewspace-148155/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DP算法是指动态规划算法,它是一种将复杂问题分解成较小子问题并逐步求解的算法。在给定问题中,动态规划算法通过将问题分解为子问题来减少计算量,并使用备忘录或表格来存储已解决的子问题的结果,以避免重复计算。引用中给出了两种不同的实现DP算法的方式。 第一种方式是使用递推的方法,通过建立一个数组来存储中间结果,从而避免重复计算。这种方式更加高效,可以更快地计算出结果。具体实现如引用中的代码所示。 第二种方式是使用递归的方法,通过定义递归函数来解决问题。这种方式相对简单易懂,但是由于递归的特性,计算速度较慢。具体实现如引用中的代码所示。 需要注意的是,在使用动态规划算法时,我们需要注意问题的状态转移方程以及边界条件,这些都是解决问题的关键。另外,动态规划算法还可以通过使用备忘录或表格来提高计算效率,避免重复计算,如引用中所示。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [动态规划(DP)的整理-Python描述](https://blog.csdn.net/MrLevo520/article/details/75676160)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值