Loading

2022.10.09 总结

1. 逐月 P5005

逐月 P5005

题意

有一个为 \(1 \sim n\) 的序列 \(a\),给定 \(a_1, a_2, b_1, b_2\),每次操作先翻转 \(a_1 \sim a_2\),再翻转 \(b_1 \sim b_2\),总共有 \(k\) 次操作,请你输出 \(k\) 次操作后的序列。

思路

52 分

暴力模拟 \(k\) 次操作。

时间复杂度

\(k\) 次操作,每次操作 \(O(n)\)

总时间复杂度 \(O(k \times n)\)

空间复杂度

用一个长度为 \(n\) 的数组来存储答案,\(O(n)\)

100 分

求出每个 \(a_i\) 的循环节,记录最终答案,输出。

时间复杂度

枚举每个元素,\(O(n)\)

每个循环节最多长度为 \(n\)\(O(n)\)

总时间复杂度为 \(O(n ^ 2)\)

空间复杂度

用一个长度为 \(n\) 的数组来记录循环节,\(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 110;

int n, k, a1, a2, b1, b2, c[N], f[N];

int F(int p){  // 求循环节
  int i = 0;
  while (p != f[1]) {
    f[++i] = p;  // 记录循环节
    if (a1 <= p && p <= a2) { 
      p = a1 + a2 - p;
    }
    if (b1 <= p && p <= b2) {
      p = b1 + b2 - p;
    }
  }
  return f[k % i + 1];
}

int main(){
  cin >> n >> k >> a1 >> a2 >> b1 >> b2;
  for (int i = 1; i <= n; i++) {
    f[1] = -1;
    c[F(i)] = i;  
  }
  for (int i = 1; i <= n; i++) {
    cout << c[i] << endl;
  }
  return 0;
}

2. 逐月 P5038

逐月 P5038

题意

有一个\(N \times N\) 的画布。在画布上,有不超过 \(9\) 个矩形,每个矩形的颜色用一个数字来表示,所有颜色都只能被使用一次。每个矩形都可以覆盖在别的矩形上。请你求出画布上仍然可见的颜色中有多少种是第一次绘制上去的。

思路

100 分

求出每种元素的矩形的左上角和右下角,判断在这个矩形中,是否存在别的颜色,如果存在,则那个颜色不可能是第一次绘制上去的。

时间复杂度

枚举颜色,\(O(9)\)

枚举每种颜色对应的矩形,\(O(n ^ 2)\)

总时间复杂度为 \(O(n ^ 2)\)

空间复杂度

记录 \(n \times n\) 的矩阵,\(O(n ^ 2)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 15;

int n, w[N][N], cnt, x[2][10], y[2][10];
char l;
bool f[10], v[10];

int main(){
  cin >> n;
  for (int i = 0; i < 10; i++) {  // 初始化
    x[1][i] = y[1][i] = INT_MIN; 
    x[0][i] = y[0][i] = INT_MAX;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      cin >> l;
      w[i][j] = l - '0';
      f[w[i][j]] = 1;
      // 记录左上角和右下角
      x[0][w[i][j]] = min(x[0][w[i][j]], i), x[1][w[i][j]] = max(x[1][w[i][j]], i);  
      y[0][w[i][j]] = min(y[0][w[i][j]], j), y[1][w[i][j]] = max(y[1][w[i][j]], j);
    }
  }
  for (int i = 1; i <= 9; i++) {
    for (int j = x[0][i]; j <= x[1][i]; j++) {
      for (int k = y[0][i]; k <= y[1][i]; k++) {
      // 枚举矩阵
        if (w[j][k] != i) {   // 如果有别的颜色
          v[w[j][k]] = 1;   // 标记颜色
        }
      }
    }
  }
  for (int i = 1; i <= 9; i++) {
    if (!v[i] && f[i]) {
      cnt++;
    }
  }
  cout << cnt;
  return 0;
}

3. 逐月 P5053

逐月 P5053

题意

给定 \(n\) 头奶牛的坐标,有一条 \(x = a\) 的无限长的栅栏和一条 \(y = b\) 的无限长的栅栏,它们在点 \((a, b)\) 相交,将农场分为四个部分,\(M\) 代表 \(4\) 个部分中包含奶牛数量的最大值,请你求出 \(M\) 的最小值。

思路

70 分

枚举行和列的坐标,再枚举每头奶牛,求出 \(M\) 的最小值。

时间复杂度

枚举坐标,\(O(b ^ 2)\)

枚举每头奶牛,\(O(n)\)

总时间复杂度为 \(O(b ^ 2 \times n)\)

空间复杂度

\(4\) 个临时变量记录四个部分的奶牛数量,\(O(1)\)

用一个变量记录 \(M\) 的最小值,\(O(1)\)

空间复杂度 \(O(1)\)

100 分

枚举两头奶牛,将行和列 \(+1\) 求出 \((a, b)\),再枚举 \(n\) 头奶牛,求出最小值。

时间复杂度

枚举两头奶牛求出 \((a, b)\)\(O(n ^ 2)\)

枚举每头奶牛,\(O(n)\)

总时间复杂度为 \(O(n ^ 3)\)

空间复杂度

\(4\) 个临时变量记录四个部分的奶牛数量,\(O(1)\)

用一个变量记录 \(M\) 的最小值,\(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 110;

int n, b, cnt = INT_MAX;

struct C{
  int x, y;
} a[N];

int main(){
  cin >> n >> b;
  for (int i = 1; i <= n; i++) {
    cin >> a[i].x >> a[i].y;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      int x = a[i].x + 1, y = a[j].y + 1;  // 枚举行和列
      int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
      for (int k = 1; k <= n; k++) {
        if (a[k].x > x) {  // 判断属于哪个部分
          if (a[k].y > y) {
            c2++;
          } else {
            c1++;
          }
        } else {
          if (a[k].y > y) {
            c4++;
          } else {
            c3++;
          }
        }
      }
      cnt = min(cnt, max(c1, max(c2, max(c3, c4))));  // 更新答案
    }
  }
  cout << cnt;
  return 0;
}
posted @ 2023-03-02 22:40  chengning0909  阅读(10)  评论(0编辑  收藏  举报