B - 简单枚举,D-Ignatius and the Princess II,F - Joseph 题目描述+参考代码+代码讲解——中山大学软件工程学院专选算法课第三次实验 选做题

这种选做题的设置真是太人性化了,为陈老师点赞

B - 简单枚举

题目描述

参考代码

#include<iostream>
using namespace std;

bool isLegal(int a, int b) {
  int used[10] = {0};

  for (int i = 0; i < 5; i++) {
    used[a % 10]++;
    a /= 10;

    used[b % 10]++;
    b /= 10;
  }

  for (int i = 0; i < 10; i++) {
    if (used[i] != 1)
      return false;
  }
  return true;
}

int main() {
  int n;
  int ncase = 0;

  while (cin >> n && n) {
    if (ncase++)
      cout << endl;

    int fghij = 1234; // start from the smallest 5-digit number
    bool legal = false;

    while (n * fghij <= 98765) {
      if (isLegal(n * fghij, fghij)) {
        legal = true;
        printf("%05d / %05d = %d\n", n * fghij, fghij, n);
      }
      fghij++;
    }

    if (!legal)
      printf("There are no solutions for %d.\n", n);
  }
  return 0;
}

代码讲解

原本是要把十位数都枚举一遍,复杂度是10^10,现在只枚举后五位,前五位用后五位和给定的n相乘得出,复杂度瞬间降到10^5.

D - Ignatius and the Princess II

题目描述

参考代码

#include<iostream>
#include<algorithm>
using namespace std;
int num[1010];
int main(){
  int n,m;
  while(cin>>n>>m){
    for(int i=1;i<=n;i++)
      num[i]=i;
    int tmp=1;
    do{
      if(tmp==m)
        break;
      tmp++;
    }while(next_permutation(num,num+n+1));
    for(int i=1;i<n;i++)
      cout<<num[i]<<" ";
    cout<<num[n]<<endl;
  }
}

代码讲解

核心就是要理解next_permutation()的使用

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 3};

    do {
        for(int num : vec) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    } while(std::next_permutation(vec.begin(), vec.end()));

    return 0;
}

具体解释如下:

  1. 第一个参数:表示序列的起始位置。通常,这是指向容器(如 vector 或数组)中第一个元素的迭代器。
  2. 第二个参数:表示序列的结束位置。对于容器(如 vector),这通常是 end() 迭代器。对于数组,这是指向数组最后一个元素之后的位置的指针。

这两个参数定义了一个半开区间 [begin, end),即包括起始位置但不包括结束位置。std::next_permutation 会在这个区间内生成下一个排列。

F - Joseph

题目描述

参考代码

#include<iostream>
using namespace std;
int a[14]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
int main(){
  int k;
  while(cin>>k&&k){
    cout<<a[k]<<"\n";
  }
}

代码讲解

打表!因为k的范围只有1-13,所以先暴力把13个算出来再乘起来就可以。

猜你喜欢

转载自blog.csdn.net/weixin_64123373/article/details/133000099