TCO2012Round1B-1-FoxAndKgram

来源:互联网 发布:软件开发市场分析 编辑:程序博客网 时间:2024/06/04 19:07
zz:http://www.strongczq.com/2012/04/tco2012round1b-1-foxandkgram.html

题目原文:
http://community.topcoder.com/stat?c=problem_statement&pm=11809&rd=15091

题目大意:
     利用int[] len表示一系列铅笔的长度,利用这些铅笔组成k-gram图案。k-gram图案的定义如下:
  • 拥有k行
  • 每行为一根长度为k的铅笔或者两个长度和为k-1的铅笔
     问:最大的k取值为多少。
     数据规模:铅笔数为[1,50],每根铅笔的长度为[1,50]。

思路:
     数据规模很小,所以直接从大到小遍历k的可能取值。显然k不会超过铅笔的个数,所以遍历范围为len.length到1。对于每一种k尝试构造该k-gram图。构造过程也比较简单,外层循环遍历每一根铅笔,如果正好长度为k则增加一行,如果长度小于k-1则通过内层循环寻找一个互补的铅笔共同构造一行,过程中用数组boolean[] used保存铅笔是否已使用的信息。如果最终构造的行数>=k则构造成功。该算法的计算复杂度为O(n^3),n为铅笔数。
     如果铅笔数的数据规模比较大,可以考虑对构图过程进行优化。使用一个数组int[] number表示各种长度的笔的个数,构造的计算复杂度为O(n)。然后遍历number的每一种长度,如果正好为k则将个数加到行数上;如果小于k-1则可以O(1)查找互补铅笔的个数,取二者个数的最小值。使用该构造方式后算法的计算复杂度优化为O(n*m),其中m为铅笔的最大长度。


Java代码:
public class FoxAndKgram{       public int maxK( int[] len)      {             int n = len.length ;             for (int k = n; k >= 1; --k){                int cnt = 0;                boolean [] used = new boolean[n];                for (int i = 0; i < n; ++i) if(!used[i]){                    used[i] = true ;                    if (len[i] == k){                        cnt++;                    } else if (len[i] < k - 1){                        for (int j = i + 1; j < n; ++j) if(!used[j]){                            if (len[j] + len[i] == k - 1){                                used[j] = true ;                                cnt++;                                break ;                            }                        }                    }                }                if (cnt >= k){                    return k;                }            }             return 0;      }}


      

原创粉丝点击