算法设计作业(四)

文章介绍了如何使用蛮力法解决两种经典算法问题:一是计算数组中的逆序对数量,给出了双重循环的直接解法以及通过归并排序优化的解决方案;二是解决鸡兔同笼问题,通过遍历所有可能的脚数来确定鸡和兔的数量。同时,还提供了一个解决学生划船问题的类似算法,确定年级的最多人数。
摘要由CSDN通过智能技术生成

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。具体思路如下:

  1. 初始化逆序对的个数为0;
  2. 使用两个嵌套循环遍历数组中的每一对元素,第一层循环变量i从0到n-2,第二层循环变量j从i+1到n-1;
  3. 判断如果ai>aj,则逆序对计数器加1;
  4. 循环结束后返回逆序对的个数。

代码如下:

#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;
 } 
 
 

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值