最小逆序对数

本文探讨了计算最小逆序对数的问题,涉及到算法、数据结构的应用,特别是排序算法和动态规划。在实现过程中,作者分享了一段关键代码,即初始化数组f[i]为整型最大值INT_MAX,这个细节在解决问题时至关重要。
摘要由CSDN通过智能技术生成

基础不扎实,写得时候被"f[i] = new int[K + 1];“这行代码坑了半天,写成"f[i] = new int[K + 1]{INT_MAX};”,还没有反应过来,哈哈。。。

/*
* 有一个长度为n的序列,每个数都是1~K中的整数。
* 现在有一些位置的数被遮住了,用-1表示。
* 你可以往这些位置填1~K中的数,使得整个序列的逆序对数最小,
* 求最小的逆序对数。
* N<=10000,K<=100
* 逆序对数:i<j,a[i]>a[j]。(有关逆序对数的性质及相关证明在同济线性代数第一章有)
* 
* 首先确保填进去数字的区间是不产生逆序对的,也就是说,填进去的数字是不严格单调增的。
* 证明:假设被遮住的区间是[i,j],记为L,区间[1,i-1]记为M,区间[j+1,n]记为N,a<b。
		1、在i处填上a,在j处填上b。(i+1~j-1这一部分没有填,所以先不看)
*		填上a产生的新的逆序对记为C(a)=M(a)+L(a)+N(a)=M(a)+N(a),
*		填上b产生的新的逆序对记为C(b)=M(b)+L(b)+N(b)=M(b)+N(b)。
*		区间L中并没有产生逆序对,所以L(a)=L(b)=0。
*		2、在i处填上b,在j处填上a。
*		填上a产生的新的逆序对记为C(a)=M(a)+L(a)+N(a),
*		填上b产生的新的逆序对记为C(b)=M(b)+L(b)+N(b)。	
*		显然情况2比情况1多产生了L(a)+L(b)的逆序对。
*		3、如果a=b,同1
*       所以填进去的数字是不严格单调增的
* 
* 创建二维数组f[i][j]表示填到了第i个数,第i个数填了j(1<=j<=K)后所产生的逆序对数C(j)
* C(j)中包含了[1,i-1]中比j大的数和[i+1,n]中比j小的数,分别记作M(j)和N(j)。
* 依次与前面已经填好的i-1个数产生的逆序对f[i-1][k](1<=k<=K),可以得到f[i-1][k]+M(j)+N(j);
* 所以f[i][j]=min(f[i-1][k]+M(j)+N(j))。
* 最终结果应该是min(f[Length][j]),Length为要填充区间的长度,1<=j<=K
*/
#include<iostream>
#include<vector>
#include<iomanip>
using namespace std;
const vector<int> A = {
   4,3,2,-1,-1,1,6};
const int Length = count(A.begin(), A.end(), -1);//求出要填充的区间长度
const int Begin = find(A.begin(), A.end(), -1) - A.begin();//需要填充数字的起始下标
const int End = Begin + Length - 1;//需要填充数字的终止下标
int single_inverse(int num,int k);//求出数组中插入第k个元素产生的新的逆序数
void 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值