一道topcoder题目的动态规划解

来源:互联网 发布:淘宝如何加入公益宝贝 编辑:程序博客网 时间:2024/05/17 20:14

 文章末尾为问题描述。
 
看到这道题的时候时间已经不多了,没多想,先对输入的segments排序,直接生成所有可能情况的组合,然后判断每个组合是否满足凸多边形的约束。结束以后分析一下,觉得太费时间了,找了个50个元素的segments和k为10的测试用例,运行时间居然要9分多钟,这显然挂了。
 
想想这个问题应该有更快的方法,突破点应该就是那些限制条件,就像整数背包问题可以用动态规划解一样。这个可以从公式C(n+1,m)=C(n,m)+C(n,m-1)说起(组合数公式,不知道怎么打公式上来),该公式可以理解为,从{1,2,...,n}选择m个的组合有C(n,m)个,这些组合为{v(1),v(2),...,v(C(n,m))},选择m-1个的组合有C(n,m-1)个,为{u(1),u(2),...,u(C(n,m-1))}。那么现在要求从{1,2,...,n,n+1}中选m个的所有组合,其实可以从前两个来构造,结果就是{v(1),v(2),...,v(C(n,m)), <u(1),n+1>,<u(2),n+1>,...,<u(C(n,m-1)),n+1>},这样就构造出从n+1个元素选m个的C(n+1,m)规模的所有组合来了。
 
再回到这道题,每个元素的范围是1到50000,最多有50个元素,并且最大的k值是10,那么选出的k个元素的最大和值就是50000*10,并且一定是整数,再根据上一段的分析,我们心里应该已经隐约有个想法了。定义一个二维数组selNums[i][j](i=1,2,...,k; j=1,2,...,50000*10),表示从n个数里选i个的和为j的组的个数,n从2开始逐渐增加到segments.size(),增加的过程中修改二维数组selNums的数据,修改的代码为selNums[ki][ mi+segments[i] ] += selNums[ki-1][mi],这条语句的意思可以从上一段的分析中得出。这样就可得到如下代码。

 

 

 但是测试后却发现,最大规模数据的运行时间还要4秒多,这不可以。经过分析可以得知,数组selNums的第二维不用弄那么大(我贴的代码中比分析中的值还要大)。我们最终需要的结果是能构成合法凸多边形的个数,所以n个数选m个(m小于k时)的和大于50000的时候,以后再加进来的边都可构成合法凸多边形(因为数据已经排过序,所以后加进来的肯定比以前加进来的大),那么就可以用selNums[i][50001]表示n条边选择i条的和大于5000的组数,这样就得到如下更快的代码。其实做点小修小补也许还能再快点。

 

 

可以到地址http://www.topcoder.com/stat?c=problem_solution&rm=301667&rd=13751&pm=9995&cr=22721553看看牛人写的代码以及系统测试数据,那代码我是没怎么看懂,另外要有账号才能看。 

 

 

Problem Statement
You are given N line segments numbered 1 to N. The lengths of these segments are given in the vector <int> segments. Compose a convex K-sided polygon, where each side is one of the given segments. Each segment can only be used once in the polygon.  Return the number of different polygons you can compose. Two polygons are considered different if there exists a segment i such that one of the polygons contains segment i but the other polygon does not.
Definition   
Class:    Polygons2
Method:    number
Parameters:    vector <int>, int
Returns:    long long
Method signature:    long long number(vector <int> segments, int K)
(be sure your method is public)   
Notes
A convex polygon can be constructed from a set of segments if the length of each segment from this set is strictly less than the sum of lengths of the remaining segments.
Constraints
segments will contain between 1 and 50 elements, inclusive.
K will be between 3 and 10, inclusive.
Each element of segments will be between 1 and 50,000, inclusive.
Examples
0)
   
{1,1,1,1}
3
Returns: 4
A nondegenerate triangle can be built using any triple from the given segments.
1)
   
{2,3,4,5}
3
Returns: 3
Any triple except {2,3,5} will do.
2)
   
{4,4,4,2,2,2}
3
Returns: 11
You can a make nondegenerate triangle using three segments of length 2, or three segments of length 4, or any two segments of length 4 with any segment of length 2.
3)
   
{10,1,4,9,20}
4
Returns: 2
One can build a convex quadrangle using segments {10,1,4,9} or {10,4,9,20}.
4)
   
{3310,1660,211,1260,160,213,884,539,17212,2025,105,120,5510}
7
Returns: 532

原创粉丝点击