博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FZU 1919 -- K-way Merging sort(记忆化搜索)
阅读量:4986 次
发布时间:2019-06-12

本文共 4958 字,大约阅读时间需要 16 分钟。

 

Problem Description

As we all known, merge sort is an O(nlogn) comparison-based sorting algorithm. The merge sort achieves its good runtime by a divide-and-conquer strategy, namely, that of halving the list being sorted: the front and back halves of the list are recursively sorted separately, then the two results are merged into the answer list. An implementation is shown as follows:

The procedure Merge(L1,L2:in List_type;L:out List_type) that we have in mind for sorting two lists is described as follows. Initialize pointers to the first item in each list L1,L2, and then

repeat

  compare the two items pointed at;

  move the smaller into L;

  move the pointer which originally points at the smaller one to the next number;

until one of L1,L2 exhausts;

drain the remainder of the unexhausted list into L;

Now let us come to the situation when there are k pointers, here k≥2. Let L be a list of n elements. Divide L into k disjoint contiguous sublists L1,L2,…,Lk of nearly equal length. Some Li’s (namely, n reminder k of them, so possibly none) will have length  , let these have the low indices: L1,L2,…,Ln%k Other Li’s will have length , and high indices are assigned: Ln%k+1,…,Lk-1,Lk. We intend to recursively sort the Li’s and merge the k results into an answer list.

We use Linear-Search-Merge here to merge k sorted lists. We find the smallest of k items (one from each of the k sorted source lists), at a cost of k-1 comparisons. Move the smallest into the answer list and advances its corresponding pointer (the next smallest element) in the source list from which it came. Again there are k items, from among which the smallest is to be selected. (When i (1 ≤ i < k) lists are empty, k-way merging sort becomes to (k-i)-way merging sort, and the draining process will start when the total order of all the elements have been found)

Given a list containing n elements, your task is to find out the maximum number of comparisons in k-way merging sort.

 Input

The first line of the input contains an integer T (T <= 100), indicating the number of cases. Each case begins with a line containing two integer n (1 ≤ n ≤ 10
100) and k (2 ≤ k ≤ 20), the number of elements in the list, and it is k-way merging sort.

 Output

For each test case, print a line containing the test case number (beginning with 1) and the maximum number of comparisons in k-way merging sort.

 Sample Input

4
2 2
3 2
100 7
1000 10

 Sample Output

Case 1: 1
Case 2: 3
Case 3: 1085
Case 4: 22005
 
 
题意:对于归并排序,本来是2-路分治,现在要求k-路分治,求n个元素下k-路分治归并排序所需要的最大比较次数?
 
思路:对于n个元素k-路分治,将元素1~n分为k段,前s=n%k段每段有n/k+1个元素,后k-s段每段有n/k个元素,那么对这k段进行归并时和2-路一样,选出这k段中的最小值放入合并后的数组,每次从k段中选出一个最小值需要比较k-1次,当每一段均剩下一个元素时,共选出了n-k个最小值,所以比较了(k-1)*(n-k)次,对于剩下的k个元素则需要比较(k-1)+(k-2)+……+1=(k-1)*k/2 次,所以共需要(k-1)*(n-k)+(k-1)*k/2次,然后递归进一步分治,注意使用记忆化搜索。
 
注意:本题数据很大所以不能用数组存值,而用的map映射的。
 
代码如下:
import java.math.BigInteger;import java.util.HashMap;import java.util.Map;import java.util.Scanner;public class Main{    static Map
dp = new HashMap
(); static BigInteger n, ans; static int k; static BigInteger dfs(BigInteger len, BigInteger x){ if(dp.containsKey(len)) return x.multiply(dp.get(len)); if(len.compareTo(BigInteger.valueOf(k))<=0){ return x.multiply(len.subtract(BigInteger.ONE)).multiply(len).divide(BigInteger.valueOf(2)); } BigInteger tmp = (BigInteger.valueOf(k).subtract(BigInteger.ONE)).multiply((len.subtract(BigInteger.valueOf(k)))); tmp = tmp.add(BigInteger.valueOf(k).multiply(BigInteger.valueOf(k).subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2))); BigInteger kk = len.mod(BigInteger.valueOf(k)); if(kk!=BigInteger.ZERO){ tmp=tmp.add(dfs(len.divide(BigInteger.valueOf(k)).add(BigInteger.ONE),kk)); } tmp = tmp.add(dfs(len.divide(BigInteger.valueOf(k)),BigInteger.valueOf(k).subtract(kk))); dp.put(len, tmp); return tmp.multiply(x); } public static void main(String[] args) { Scanner in = new Scanner(System.in); int T = in.nextInt(); for(int cas=1; cas<=T; cas++){ dp.clear(); n = in.nextBigInteger(); k = in.nextInt(); ans=dfs(n, BigInteger.ONE); System.out.println("Case "+cas+": "+ans); } }}

 

下面这个是我先用c++写的版本,用来验证算法,上面的java是用这c++代码改写的(其实一样)。

#include 
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long LL;LL n,k;map
mp;LL dfs(LL len,LL x){ if(mp.count(len)) return x*mp[len]; if(len<=k) return x*(len-1)*len/2; LL tmp=(k-1)*(len-k); tmp+=k*(k-1)/2; tmp+=dfs(len/k+(len%k!=0),(len%k)); tmp+=dfs(len/k,(k-len%k)); mp[len]=tmp; return tmp*x;}int main(){ while(scanf("%lld%lld",&n,&k)!=EOF) { mp.clear(); LL ans=dfs(n,1); cout<<"final ans = "<
<

 

转载于:https://www.cnblogs.com/chen9510/p/7629947.html

你可能感兴趣的文章
关于nginx反向代理504 gateway time-out配置
查看>>
带有构造方法的枚举
查看>>
idea代码出现Usage of API documented as @since 1.8+ less... (Ctrl+F1)
查看>>
Quartz.NET 2.0 学习笔记(2) :和1.0的几点不同
查看>>
ext4 goes faster than ext3(From 51cto)
查看>>
初识WEB移动端开发
查看>>
关于<meta name="viewport" content="width=device-width, initial-scale=1.0">的解释
查看>>
浪味仙
查看>>
LUOGU P4777 【模板】扩展中国剩余定理(EXCRT)
查看>>
[转]expect的安装
查看>>
HDU 1070 [Milk] 贪心
查看>>
关于 IsLocalUrl 方法的注意事项
查看>>
ln -s 软连接介绍
查看>>
计算到今天多少天--字符集要选GB2312
查看>>
《Python数据分析与挖掘实战》-第四章-数据预处理
查看>>
觉得父母思想过时,有时甚至阻碍到自己,如何有效沟通并说服?
查看>>
P3480 [POI2009]KAM-Pebbles 阶梯NIM
查看>>
STM32之CAN ---CAN ID过滤器分析
查看>>
android studio ndk 调试
查看>>
ylb-ASP.NET技术搭建不错的网站列表
查看>>