一、PAT A1140 Look-and-say Sequence
- 就是简单的模拟啦。参考代码如下。
#include<iostream>
#include<string>
using namespace std;
int main() {
int d, n;
string s;
cin >> d >> n;
s = '0' + d;
while (--n) {
string t;
int i = 0;
while (i < s.size()) {
t += s[i++];
int cnt = 1;
while (i < s.size() && s[i] == s[i - 1]) {
cnt++;
i++;
}
t += '0' + cnt;
}
s = t;
}
cout << s << endl;
return 0;
}
二、PAT A1141 PAT Ranking of Institutions
- 散列的思想,读入数据时就按学校将考生分类,然后再排序。参考代码如下。
#include<cstdio>
#include<string>
#include<unordered_map>
#include<vector>
#include<algorithm>
#include<cctype>
#include<cstring>
using namespace std;
const float eps = 1e-3;
struct institution {
int rank, NS = 0;
string school;
float TWS = 0;
};
bool cmp(institution &i1, institution &i2) {
if ((int)i1.TWS != (int)i2.TWS)
return i1.TWS > i2.TWS;
else if (i1.NS != i2.NS)
return i1.NS < i2.NS;
else return i1.school < i2.school;
}
unordered_map <string, institution> m;
vector <institution> v;
int main() {
int n, score;
string id, school;
id.resize(8);
school.resize(8);
scanf("%d", &n);
for (int i = 0; i < n; i++) {
memset(&id[0], '\0', 8);
memset(&school[0], '\0', 8);
scanf("%s%d%s", &id[0], &score, &school[0]);
for (int i = 0; school[i] != '\0'; i++) school[i] = tolower(school[i]);
m[school].NS++;
m[school].school = school;
if (id[0] == 'T') m[school].TWS += 1.5*score;
else if (id[0] == 'A') m[school].TWS += score;
else m[school].TWS += score / 1.5;
}
for (auto it : m) v.push_back(it.second);
sort(v.begin(), v.end(), cmp);
printf("%d\n", v.size());
int i = 0;
while (i < v.size()) {
v[i].rank = i + 1;
i++;
while (i < v.size() && (int)v[i].TWS == (int)v[i - 1].TWS) {
v[i].rank = v[i - 1].rank;
i++;
}
}
for (auto it : v)
printf("%d %s %d %d\n", it.rank, &it.school[0], (int)it.TWS, it.NS);
return 0;
}
三、PAT A1142 Maximal Clique
- 判断是否为最大连通分量。首先判断是否连通,如果连通,则尝试将每一个不在连通分量中的顶点加入该连通分量中,若加入后仍是连通分量,则说明不是最大连通分量。参考代码如下。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 210;
bool G[maxn][maxn], in_clique[maxn];
int Nv, Ne, M, K;
int v[maxn];
int main() {
fill(G[0], G[0] + maxn * maxn, false);
scanf("%d%d", &Nv, &Ne);
int v1, v2;
while (Ne--) {
scanf("%d%d", &v1, &v2);
G[v1][v2] = G[v2][v1] = true;
}
scanf("%d", &M);
while (M--) {
fill(in_clique, in_clique + maxn, false);
scanf("%d", &K);
for (int i = 1; i <= K; i++) {
scanf("%d", &v[i]);
in_clique[v[i]] = true;
}
bool clique = true;
for (int i = 1; i <= K; i++) {
if(clique)
for (int j = i + 1; j <= K; j++) {
if (!G[v[i]][v[j]]) {
clique = false;
break;
}
}
}
if (clique) {
bool max_clique = true;
for (int i = 1; i <= Nv; i++) {
if (!in_clique[i]) {
int j = 1;
while (j <= K) {
if (G[i][v[j]]) j++;
else break;
}
if (j == K + 1) {
max_clique = false;
break;
}
}
}
if (max_clique) printf("Yes\n");
else printf("Not Maximal\n");
}
else printf("Not a Clique\n");
}
return 0;
}
四、PAT A1143 Lowest Common Ancestor
- 这题我一开始的思路是建树,然后寻找每个结点的祖先,然后再比较判断。花了一个多小时弄完后发现最后一个测试点会超时,死活都过不去。后来翻看了这个萌妹子的博客,发现思路非常精巧。BST 先序序列中第一个值在 a 和 b 之间的结点即为 a, b 的最近共同祖先(可以想象 BST 的中序遍历,a, b 的共同祖先一定在 a 和 b 之间,先序遍历可以保证找到的第一个值为 a, b 的最近共同祖先)。参考代码如下。
-
#include<cstdio> #include<unordered_map> using namespace std; const int maxn = 10010; unordered_map <int, bool> m; int pre[maxn]; int main() { int M, N, u, v, t; scanf("%d%d", &M, &N); for (int i = 0; i < N; i++) { scanf("%d", &pre[i]); m[pre[i]] = true; } while (M--) { scanf("%d%d", &u, &v); if (!m[u] && !m[v]) printf("ERROR: %d and %d are not found.\n", u, v); else if (!m[u] && m[v]) printf("ERROR: %d is not found.\n", u); else if (m[u] && !m[v]) printf("ERROR: %d is not found.\n", v); else { for (int i = 0; i < N; i++) { t = pre[i]; if ((u <= t && t <= v) || (v <= t && t <= u)) break; } if (t == u) printf("%d is an ancestor of %d.\n", u, v); else if (t == v) printf("%d is an ancestor of %d.\n", v, u); else printf("LCA of %d and %d is %d.\n", u, v, t); } } return 0; }
- 这里也把我的非常复杂的代码贴在这里,以供参考。
//未通过
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 10010;
struct node {
int v;
node* parent = NULL;
node* lchild = NULL;
node* rchild = NULL;
};
int pre[maxn], in[maxn];
node* build(int preL, int preR, int inL, int inR) {
if (preL > preR) return NULL;
node* root = new node;
root->v = pre[preL];
int k;
for (k = inL; k != inR; k++)
if (in[k] == pre[preL]) break;
int num = k - inL;
root->lchild = build(preL + 1, preL + num, inL, k - 1);
root->rchild = build(preL + num + 1, preR, k + 1, inR);
if (root->lchild) root->lchild->parent = root;
if (root->rchild) root->rchild->parent = root;
return root;
}
node* search(node* root, int n) {
if (root == NULL) return NULL;
if (n == root->v) return root;
else if (n < root->v) return search(root->lchild, n);
else return search(root->rchild, n);
}
int main() {
int M, N, u, v;
scanf("%d%d", &M, &N);
for (int i = 0; i < N; i++) {
scanf("%d", &pre[i]);
in[i] = pre[i];
}
sort(in, in + N);
node* BST = build(0, N - 1, 0, N - 1);
while (M--) {
scanf("%d%d", &u, &v);
node* nu = search(BST, u);
node* nv = search(BST, v);
if (nu == NULL && nv == NULL)
printf("ERROR: %d and %d are not found.\n", u, v);
else if (nu != NULL && nv == NULL)
printf("ERROR: %d is not found.\n", v);
else if (nu == NULL && nv != NULL)
printf("ERROR: %d is not found.\n", u);
else {
vector <int> ancestor_u;
bool found = false;
while (nu && !found) {
if (nu->v == v) {
printf("%d is an ancestor of %d.\n", v, u);
found = true;
}
ancestor_u.push_back(nu->v);
nu = nu->parent;
}
while (nv && !found) {
if (nv->v == u) {
printf("%d is an ancestor of %d.\n", u, v);
found = true;
}
else for (int i = 1; i < ancestor_u.size(); i++)
if (nv->v == ancestor_u[i]) {
printf("LCA of %d and %d is %d.\n", u, v, ancestor_u[i]);
found = true;
break;
}
nv = nv->parent;
}
}
}
return 0;
}