K歌时碰到的问题2

 现在来考虑一下最优的解决方案。

 

假设s = {a, b, c, d, e} 我们需要将它变换成{e, d, a, c, b}。很明显,这里可以将s进行划分:

s = {s1, s2} 其中,s1 = {a, b, c}. s2 = {d, e}。所以,问题抽象成,将 s= {s1, s2} 变成 s = {s2, s1}。值得注意的是,这里没有考虑s1,s2的内部顺序。但这种划分很明显让问题简化了很多。这意味这,我们只需先将s1的内部顺序排好,然后再把s2排到s1的前面就行了。但有些时候,s = {1, 2, ..n}并不能划分为更小的单元。

比如 假设n为偶数,s = {1, 2, ... n} ,现要将s 变成 s' = {1, 3, 5, ..2, 4, 6, ..n}。在这种情况下,不存在任何的划分{s1, s2,.. sm}(m < n) ,使得s->s' 转化成为求解 {s1, s2, .. sm}->{si, .. sj}

但是,我们可以朝着这个方向来演变。

现在,将给出一个一般化的方法来构造最优解。

首先,假设M 是序列from 和 序列to之间的划分,设N(M)为M中划分的集合的个数, 我们可以用一个function MatchValue( S from, S to)来完成。

假设M将from 被划分成 {s1, s2, sm},将to划分成{s3,s2, ..sm, ..s1}。(可以是任何{s1, .. sm}m个元素排列)

那么,我们的问题被抽象成求解,{s1, s2.. sm} -> {s3, s2... sm, .. s1},如果我们找到了这组解,我们还需要对s1, s2, ... sm各自元素的内部顺序进行处理,显然这是一个递归的过程,我们能够找到{s1, s2.. sm} -> {s3, s2... sm, .. s1}的最优解的一般方法,也同样都找到排列s1里内部元素的一般方法。

依次尝试着移动s2, s3.. sm到最左边,每一次都与结果s' = {s3, s2, .. sm .. s1}进行MatchValue求解,选MatchValue最小的方法。

int min = n, minindex = -1;

for_each si in S

{

  int v = MatchValue(si, s');

  if (v < min)

  {

    min = v; minindex = i;

  }

}

 

将s-minindex移动到最左边,然后重复上面的操作,直至等于 s'为止。

至于,求解最优解本身算法的复杂度而言,这个算法是O(n*n)的,应该还有更好解。

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值