Back

NOIP2008普及组题解

ISBN号码

对于一个形式为“x-xxx-xxxxx-x”的ISBN,判断其是否合法。

题解

模拟,需要特别处理X。

#include <bits/stdc++.h>
using namespace std;
int main() {
  char a[100];
  scanf("%s", a);
  int n = strlen(a);
  int s = 0;
  for (int i = 0, j = 0; i < n - 1; i++) {
    if (a[i] != '-') {
      j += 1;
      s += (a[i] - '0') * j;
    }
  }
  if (s % 11 == (a[n-1] - '0') || s % 11 == 10 && a[n-1] == 'X') {
    puts("Right");
  } else {
    a[n-1] = s % 11 + '0';
    if(s%11 == 10) {
      a[n-1] = 'X';
    }
    puts(a);
  }
}

排座椅

题解

贪心,分别统计每一行每一列加一条通道能隔开的数量,优先选择最多的K条横向的和L条纵向的。

#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
int m, n, k, l, d;
pair<int, int> row[N], col[N];
int main() {
  cin >> m >> n >> k >> l >> d;
  for (int i = 1; i <= max(n, m); i++) {
    row[i].second = i;
    col[i].second = i;
  }
  for (int i = 1; i <= d; i++) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    if (x1 == x2) {
      col[min(y1, y2)].first += 1;
    }
    if (y1 == y2) {
      row[min(x1, x2)].first += 1;
    }
  }
  sort(row + 1, row + m + 1);
  reverse(row + 1, row + m + 1);
  sort(col + 1, col + n + 1);
  reverse(col + 1, col + n + 1);
  for (int i = 1; i <= k; i++) {
    swap(row[i].first, row[i].second);
  }
  sort(row + 1, row + k + 1);
  for (int i = 1; i <= k; i++) {
    cout << row[i].first;
    if (i != k) cout << ' ';
  }
  cout << endl;
  for (int i = 1; i <= l; i++) {
    swap(col[i].first, col[i].second);
  }
  sort(col + 1, col + l + 1);
  for (int i = 1; i <= l; i++) {
    cout << col[i].first;
    if (i != l) cout << ' ';
  }
}

传球游戏

有n个同学排成一个圈,从1号同学开始传球,每次可以向左传或向右传,问传m次回到1号同学有多少种方式。

题解

递推,用f[i][j]表示传了i次球,最后停留在j号同学的种数,转移方程为$$f[i][j] = f[i-1][j的左边] + f[i-1][j的右边]$$

#include <bits/stdc++.h>
using namespace std;
const int N = 35;
long long f[N][N];
int n, m;
int main() {
  f[0][1] = 1;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    for (int j = 1; j <= n; j++) {
      f[i][j] = (j == 1 ? f[i-1][n] : f[i-1][j-1]) + (j == n ? f[i-1][1] : f[i-1][j+1]);
    }
  }
  cout << f[m][1] << endl;
}

立体图

题解

烂题。按从左往右,从前往后,从下往上的顺序画,之前存在的直接覆盖。

#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int a[N][N];
int n, m;
char c[2005][2005];
char b[6][8] = {
  "..+---+",
  "./   /|",
  "+---+ |",
  "|   | +",
  "|   |/.",
  "+---+..",
};
int main() {
  cin >> n >> m;
  int mx = 0;
  for (int i = 1; i <= n; i++) {
    for (int j = 1 ;j <= m ; j++) {
      scanf("%d", &a[i][j]);
      mx = max(a[i][j], mx);
    }
  }
  int px = 1e9, py = 0;
  int qx = 0, qy = 0;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      for (int k = 1; k <= a[i][j]; k++) {
        int x = 3 * (mx-k) + 2 * (i-1);
        int y = 4 * (j-1) + 2 * (n-i);
        px = min(px, x);
        for(int p = 0; p < 6; p++) {
          for(int q = 0; q < 7; q++) {
            if (b[p][q] == '.') continue;
            c[x + p][y + q] = b[p][q];
            qx = max(qx, x + p);
            qy = max(qy, y + q);
          }
        }
      }
    }
  }
  for (int i = px; i <= qx; i++) {
    for (int j = 0; j <= qy; j++) {
      if (c[i][j] == 0) cout << '.';else cout << c[i][j];
    }
    cout << endl;
  }
}