2020010944
1.给定一个整数数组 A=(a0,a1,…an-1),若 i<j 且 ai>aj,则<ai,aj>就为一个逆序
对。例如数组(3,1,4,5,2)的逆序对有<3,1>,<3,2>,<4,2>,<5,2>。设计一个算法采用蛮力法求 A 中逆序对的个数即逆序数。
思路:蛮力法求解逆序对的个数即逆序数,可以使用双重循环遍历数组中的每一对元素,判断是否构成逆序对,如果是则计数器加1。具体思路如下:
- 初始化逆序对的个数为0;
- 使用两个嵌套循环遍历数组中的每一对元素,第一层循环变量i从0到n-2,第二层循环变量j从i+1到n-1;
- 判断如果ai>aj,则逆序对计数器加1;
- 循环结束后返回逆序对的个数。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n,a[N],q[N];
int ans;
int merge_solve(int a[] ,int l ,int r)
{
if(l >= r) return 0;
int mid = (l + r) >> 1;
ans = merge_solve(a,l,mid) + merge_solve(a,mid + 1,r);
int k = 0;
int i = l,j = mid + 1;
while(i <= mid && j <= r)
{
if(a[i] <= a[j]) q[k++] = a[i++];
else q[k++] = a[j++],ans += mid - i + 1;
}
while(i <= mid) q[k++] = a[i++];
while(j <= r) q[k++] = a[j++];
for(int i = l,j = 0;i <= r;i++,j++) a[i] = q[j];
return ans;
}
int BF_solve(int a[])
{
ans = 0;
for(int i = 0;i < n - 1;i ++)
{
for(int j = i + 1;j < n;j ++)
{
if(a[i] > a[j]) ans ++;
}
}
return ans;
}
int main()
{
cin >> n;
for(int i = 0;i < n;i ++) cin >> a[i];
//cout << merge_solve(a,0,n-1) << endl;
cout << BF_solve(a) << endl;
return 0;
}
该问题的优化方式之一:使用归并排序解决逆序对的问题,因为在归并排序的过程中,对于每个子序列,它的逆序对数量可以通过合并两个有序子序列的方法来计算得出。具体来说,假设有两个有序子序列L和R,且L中的某个元素l大于R中的某个元素r,那么在合并L和R时,l一定在r的前面,因此此时就会产生逆序对。因此,在归并排序的过程中,每次合并两个有序子序列时,就可以计算出这两个子序列之间的逆序对数量,然后将逆序对数量累加起来即可得到整个序列的逆序对数量。算法时间复杂度为O(nlogn)。代码见上merge_solved()
运行结果:
2.有一群鸡和一群兔,它们的只数相同,它们的脚数都是三位数,且这两个三位数
的各位数字只能是 0、1、2、3、4、5。设计一个算法用蛮力法求鸡和兔的只数各是多
少?它们的脚数各是多少?
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int n;
bool st[N];
bool check(int x)
{
while(x)
{
int num = x % 10;
if(num == 0 || num == 1 || num == 2|| num == 3 || num == 4 || num == 5) x /= 10;
else return false;
}
return true;
}
int main()
{
cout << "鸡兔只数: |" << "鸡脚数: |" << "兔脚数: |" << endl;
for(int i = 100 ; i <= 999;i ++)
{
if(check(i) && !st[i])
{
if(i % 2 == 0)
{
if(check(i/2 * 4)&& (i/2*4) <= 999 && (i/2*4) >= 100)
{
cout << i/2 << " " << i << " " << i / 2 * 4 << endl;
st[i/2*4] = st[i] = true;
}
}
else if(i % 4 == 0)
{
if(check(i/4 * 2) && (i/4*2) <= 999 && (i/4*2) >= 100)
{
cout << i/4 << " " << i/4*2 << " " << i << endl;
st[i/4*2] = true;
st[i] = true;
}
}
}
}
}
运行结果:
3.某年级的同学集体去公园划船,如果每只船坐 10 人,那么多出 2 个座位;如果每
只船多坐 2 人,那么可少租 1 只船,设计一个算法用蛮力法求该年级的最多人数?
思路:设船数为x,则该年级人数为N = 10 * x - 2;又因为当每船多坐2人时,可以少租一辆船,此时船容量为12,此时船数为x-1,但是最后一条船可以坐的人数范围是1-12,所以人数N所满足的不等式为:N > 12 * (x - 2) && N <= 12 * (x- 1 ) 。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int main()
{
for(int x = 1;x <= 30;x ++) //船
{
if(10 * x - 2 > 12 * (x - 2) && 10 * x - 2 <= 12 * (x - 1))
cout << 10 * x - 2 << endl;
}
return 0;
}
运行结果: