问题
代码
#include<bits/stdc++.h>
using namespace std;
// 定义变量n
int n;
// 定义计数器cnt,用于统计组合数量
int cnt;
// 定义答案变量ans
int ans;
// 定义一个数组CASE,用来存储每个位置上的数值
int CASE[60];
// 函数cal()用于计算每一种情况下逆序对的数量
void cal()
{
// 双层循环遍历每一个可能的逆序对
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
// 如果找到一个逆序对,则增加逆序对总数
if(CASE[i] > CASE[j]) ans++;
}
}
}
// 主函数main()
int main()
{
// 初始化n为51
n = 51;
// 使用四层循环枚举所有可能的两组不同的索引
for(int d11 = 1; d11 <= n; d11++)
for(int d12 = d11+1; d12 <= n; d12++)
for(int d21 = 1; d21 <= n; d21++)
for(int d22 = d21+1; d22 <= n; d22++)
{
// 每进入一次内层循环,计数器cnt加一
cnt++;
// 将数组CASE初始化为1到n的序列
for(int i = 1; i <= n; i++) CASE[i] = i;
// 交换CASE中索引d11和d12的值
swap(CASE[d11], CASE[d12]);
// 交换CASE中索引d21和d22的值
swap(CASE[d21], CASE[d22]);
// 调用cal()计算当前序列下的逆序对数量
cal();
}
// 输出逆序对总数除以组合数量的平均值,保留四位小数
cout << setprecision(4) << (double)ans / cnt;
}
#include<bits/stdc++.h>
using namespace std;
// 定义全局变量
int n;
int cnt;
int ans;
int CASE[60];
int M[60];
// 合并排序的合并函数
void merge(int l, int r)
{
// 如果左边界小于右边界,递归划分数组
if(l < r)
{
// 计算中间位置
int mid = (l+r) >> 1;
// 递归地对左右两边进行排序
merge(l, mid);
merge(mid+1, r);
// 初始化临时指针和两个子数组的指针
int tmp = l, i = l, j = mid+1;
// 当两个子数组都有元素时
while(i <= mid && j <= r)
{
// 如果左侧的数大于右侧的数
if(CASE[i] > CASE[j])
{
// 更新逆序对数量
ans += mid - i + 1;
// 将较小的元素放入辅助数组
M[tmp++] = CASE[j++];
}
// 否则将左侧的元素放入辅助数组
else M[tmp++] = CASE[i++];
}
// 如果左侧还有剩余元素,依次放入辅助数组
while(i <= mid) M[tmp++] = CASE[i++];
// 如果右侧还有剩余元素,依次放入辅助数组
while(j <= r) M[tmp++] = CASE[j++];
// 将排序后的辅助数组复制回原数组
memcpy(CASE+l, M+l, sizeof(int)*(r-l+1));
}
}
// 主函数
int main()
{
// 初始化n为51
n = 51;
// 枚举所有可能的两对不同的索引
for(int d11 = 1; d11 <= n; d11++)
for(int d12 = d11+1; d12 <= n; d12++)
for(int d21 = 1; d21 <= n; d21++)
for(int d22 = d21+1; d22 <= n; d22++)
{
// 对每一对索引计数
cnt++;
// 初始化数组CASE为1到n
for(int i = 1; i <= n; i++) CASE[i] = i;
// 交换两对索引对应的元素
swap(CASE[d11], CASE[d12]);
swap(CASE[d21], CASE[d22]);
// 使用归并排序计算逆序对的数量
merge(1,n);
}
// 输出平均逆序对数量
cout << setprecision(4) << (double)ans / cnt;
}
疑惑
在编写代码时,我将
// 将排序后的辅助数组复制回原数组
memcpy(CASE+l, M+l, sizeof(int)*(r-l+1));
放到l < r的判断体之外,结果输出为0,查验发现CASE[i] > CASE[j]判断体不会进入。
一开始我以为是l > r导致memcpy出现错误
于是我换成
for(int i = l; i <= r; i++)
{
CASE[i] = M[i];
}
但是情况依旧。
解答
分到单个元素的时候不应该覆盖。结果覆盖了。
倒数第二层的比较就全是0和0的了,难怪进不去第一个判断体。
上面也全废了,ans=0。