0
点赞
收藏
分享

微信扫一扫

蓝桥杯 Day10 java组 分治

IT影子 2022-02-06 阅读 70

        算法里面的“分治”,是把一个大问题分成小问题,各个击破,“分而治之(Divide and Conquer)”。而分治算法的具体操作,是把原问题分成 k 个较小规模的子问题,对这 k 个子问题分别求解。如果子问题不够小,那么把每个子问题再划分为规模更小的子问题。这样一直分解下去,直到问题足够小,很容易求出这些小问题的解为止。

能用分治法的题目,需要符合两个特征:

  • 平衡子问题:子问题的规模大致相同。能把问题划分成大小差不多相等的 k 个子问题,一般是 k=2,即分成两个规模相等的子问题。编码的时候,每次分成两部分,然后继续分成两部分 ⋯ 该步骤和二分法很像。 当然,二分法也是分治法,只是二分法的应用场合非常简单。
  • 独立子问题:子问题之间相互独立。这是区别于动态规划算法的根本特征,在动态规划算法中,子问题是相互联系的,而不是相互独立的。

分治法的思想,几乎就是递归的过程,用递归程序实现分治法是很自然的。用分治法建立模型时,解题步骤分为三步:

  • 分解(Divide):把问题分解成独立的子问题;
  • 解决(Conquer):递归解决子问题;
  • 合并(Combine):把子问题的结果合并成原问题的解。

样例输入

3 2

样例输出

#2: A->B
7
import java.util.Scanner;

public class Main {
    private static int ans = 0;
    private static int M;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        M = scanner.nextInt();
        fun('A', 'B', 'C', N);

        System.out.println(ans);
    }

    public static void fun(char A, char B, char C, int n) {
        if (n == 1) {
            ans++;
            if (M == ans) System.out.println("#" + M + ":" + A + "->" + C);
            return;
        } else {
            fun(A, C, B, n - 1);
            ans++;
            if (M == ans) System.out.println("#" + M + ":" + A + "->" + C);
            fun(B, A, C, n - 1);
        }
    }
}

归并排序

#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef  long  long  ll;
int a[N], b[N];
ll cnt;
void Merge(ll l, ll mid, ll r){
     ll i=l, j = mid+1, t=0;
     while(i <= mid && j <= r){
          if(a[i] > a[j]){
               b[t++] = a[j++];
               cnt += mid-i+1;                //记录逆序对数量
          }
          else b[t++]=a[i++];
     }
   //一个子序列中的数都处理完了,另一个还没有,把剩下的直接复制过来:
    while(i <= mid)   b[t++]=a[i++];
    while(j <= r)     b[t++]=a[j++];
    for(i=0; i<t; i++)  a[l+i] = b[i];     //把排好序的b[]复制回a[]
}
void Mergesort(ll l, ll r){
    if(l<r){
         ll  mid = (l+r)/2;                   //平分成两个子序列
         Mergesort(l, mid);
         Mergesort(mid+1, r);
         Merge(l, mid, r);                    //合并
    }
}
int main(){
    int n,k;
    cin >>n;
    cnt = 0;
    for(int i=0;i<n;i++)  scanf("%d", &a[i]);
    Mergesort(0,n-1);                     //归并排序
    cout <<cnt;
    return 0;
}

快速排序

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = sc.nextInt();
        quick_sort(a, 0, n - 1);
        for (int i = 0; i < n; i++) System.out.print(a[i] + " ");
        System.out.print("\n");
        for (int i = n - 1; i >= 0; i--) System.out.print(a[i] + " ");
        System.out.print("\n");
    }

    public static void quick_sort(int[] a, int l, int r) {
        if (l >= r) return;
        int i = l, j = r, base = a[l];
        while (i < j) {
            while (a[j] >= base && i < j) j--;
            while (a[i] <= base && i < j) i++;
            swap(a, i, j);
        }
        swap(a, l, j);
        quick_sort(a, l, j - 1);
        quick_sort(a, i + 1, r);
    }

    public static void swap(int[] a, int i, int j) {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
}
举报

相关推荐

Java Web day10

自学Java day10

Java学习Day10

学习Java Day10

Day10

day10

0 条评论