【SCUTOJ】大一上OJ题回顾
大一上OJ题回顾
第一章
问题 A: 判断坐标区域
简单的逻辑判断,注意多组读入即可。
#include<iostream>
using namespace std;
bool judge(int x) {
return x >= -2 && x <= 2;
}
int main() {
int x, y;
while (cin >> x >> y) {
cout << boolalpha << (judge(x) && judge(y)) << endl;
}
return 0;
}
问题 B: 条件表达式求最小值
不考虑条件表达式的问题,三个数的判断直接拿前两个数的较小值和第三个数比较即可。
#include<iostream>
using namespace std;
int myMin(int x, int y) {
return x <= y ? x : y;
}
int main() {
int x, y, z;
while (cin >> x >> y >> z) {
cout << myMin(myMin(x, y), z) << endl;
}
return 0;
}
问题 C: 分解数字
逐个模10再削减即可。
#include<iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
while (n) {
cout << " " << n % 10;
n /= 10;
}
cout << endl;
}
}
问题 D: 24点
莫名其妙就蹦出来一道超标题,主要是要保证枚举不漏。
24点事实上是可以有分数的情况的,因此需要做除法,那么相等就是靠精度维持。
枚举的要素:
- 数字顺序
- 运算顺序
- 三个符号
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
vector<int> types = {0, 1, 2, 3};
double calc(double x, int op, double y) {
switch (op) {
case 0: return x + y;
case 1: return x - y;
case 2: return x * y;
case 3:
if (y != 0) return x / y;
else return 1e15;
}
return 1e15;
}
bool equal(double x, double y) {
return fabs(x - y) < 1e-6;
}
bool judge(vector<double> nums, vector<int> ops) {
double res1 = calc(calc(calc(nums[0], ops[0], nums[1]), ops[1], nums[2]), ops[2], nums[3]);
double res2 = calc(calc(nums[0], ops[0], nums[1]), ops[1], calc(nums[2], ops[2], nums[3]));
return equal(res1, 24.0) || equal(res2, 24.0);
}
int main() {
vector<double> nums(4, 0);
while (cin >> nums[0] >> nums[1] >> nums[2] >> nums[3]) {
sort(nums.begin(), nums.end());
int flag = 0;
do {
for (int a : types)
for (int b : types)
for (int c : types) {
vector<int> ops = {a, b, c};
if (judge(nums, ops)) {
flag = 1;
break;
}
}
} while (next_permutation(nums.begin(), nums.end()));
cout << (flag ? "YES" : "NOT") << endl;
}
}
第二章
问题 A: 菲波那契数列
用数组维护数列,可以复用。
#include<iostream>
#include<vector>
using namespace std;
vector<unsigned long long> fib;
int main() {
fib.push_back(1);
fib.push_back(1);
int n;
while (cin >> n) {
if (fib.size() <= n) {
while (fib.size() <= n) {
fib.push_back(fib[fib.size() - 2] + fib[fib.size() - 1]);
}
cout << fib[n] << endl;
} else {
cout << fib[n] << endl;
}
}
return 0;
}
问题 B: 打印正方形
数好对应空格数量即可。
#include<iostream>
using namespace std;
int main() {
int n;
while (cin >> n) {
for (int i = 0; i < n; i++) cout << "*";
cout << endl;
for (int i = 0; i < n-2; i++) {
cout << "*";
for (int j = 0; j < n-2; j++) cout << " ";
cout << "*";
cout << endl;
}
for (int i = 0; i < n; i++) cout << "*";
cout << endl << endl;
}
}
问题 C: 进制转换
主要涉及两个库的相关表示:
- 二进制可以用bitset
表示 - 十六进制、八进制可以用hex、oct表示,位数利用setw()和setfill()控制
#include<iostream>
#include<bitset>
#include<iomanip>
using namespace std;
int main() {
int n;
while (cin >> n) {
cout << " " << bitset<8>(n);
cout << " " << hex << setw(2) << setfill('0') << n << endl;
}
return 0;
}
问题 D: 因数分解
考察枚举和素数判断,加上个素数表可以复用。
#include<iostream>
#include<vector>
using namespace std;
vector<int> primeList;
bool judgePrime(int x) {
for (int i = 2; i * i < x; i++) {
if (x % i == 0) return false;
}
return true;
}
void generatePrime() {
for (int i = 2; i <= 135; i++) {
if (judgePrime(i)) primeList.push_back(i);
}
}
int main() {
generatePrime();
int n;
while (cin >> n) {
for (int x : primeList) {
if (n == 0) break;
while (n % x == 0) {
cout << " " << x;
n /= x;
}
}
cout << endl;
}
return 0;
}
第三章
问题 A: 勒让德多项式
递归的纯粹使用,加上个记忆化搜索优化。
#include<iostream>
#include<iomanip>
#include<cstring>
#include<iomanip>
using namespace std;
float p[105];
float P(int n, float x) {
if (n == 0) return 1;
if (n == 1) return x;
if (p[n]) return p[n];
return p[n] = ((2*n-1)*x*P(n-1, x) - (n-1) * P(n-2, x)) / (float)(n);
}
int main() {
float x;
int n;
while (cin >> x >> n) {
memset(p, 0, sizeof(p));
p[0] = 1, p[1] = x;
cout << fixed << setprecision(2) << P(n, x) << endl;
}
}
问题 B: 计算数值
考察pow函数的利用
还有iomanip库的fixed和setprecision()的使用
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
float sumPow(float n, int x) {
float sum = 0;
for (int i = 1; i <= n; i++) sum += pow(i, x);
//cout << n << " " << x << " " << sum << endl;
return sum;
}
int main() {
float m, n, p;
while (cin >> m >> n >> p) {
cout << fixed << setprecision(4) << (sumPow(m, 1) + sumPow(n, 3)) / sumPow(p, 5) << endl;
}
return 0;
}
问题 C: 蛇形矩阵
设想在一个矩阵上填数字,在矩阵上按照对角线填数,注意边界即可。
#include<iostream>
using namespace std;
int mat[1005][1005];
int main() {
int n;
while (cin >> n) {
int x = 1, y = 1;
int mx = -1, my = -1;
bool flag = 0;
for (int i = 1; i <= n; i++) {
mat[x][y] = i;
mx = max(mx, x);
my = max(my, y);
if (x == 1) x = y + 1, y = 1;
else x -= 1, y += 1;
}
for (int i = 1; i <= mx; i++) {
flag = 0;
for (int j = 1; j <= my; j++) {
if (mat[i][j]) {
if (j == 1) cout << mat[i][j];
else cout << " " << mat[i][j];
flag = 1;
}
}
if (flag) cout << endl;
}
}
return 0;
}
问题 D: 回文数判断
把读入的数字视作字符串,一切都会简单很多。
#include<iostream>
using namespace std;
string output(bool x) {
return x ? "YES" : "NO";
}
int main() {
string n;
while (cin >> n) {
int i = 0, j = n.size() - 1;
bool res = 1;
while (i <= j) {
if (n[i] != n[j]) {
res = 0;
break;
}
i++, j--;
}
cout << output(res) << endl;
}
return 0;
}
第四章
问题 A: 矩阵求和
先把整个矩阵填上1,再考虑非1数字,顺便求和。
#include<iostream>
using namespace std;
int mat[25][25];
void matInit(int n) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mat[i][j] = 1;
}
int main() {
int n;
while (cin >> n) {
matInit(n);
int sum = 0;
for (int x = 2; x <= n; x++) {
int i = x, j = 1;
while (i <= n) {
mat[i][j] = x;
i++, j++;
sum += x;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (j == n) cout << mat[i][j];
else cout << mat[i][j] << " ";
}
cout << endl;
}
cout << sum << endl;
}
return 0;
}
问题 B: 数组输出
结构体排序,利用sort()以及cmp函数即可。
#include<iostream>
#include<algorithm>
using namespace std;
class Node {
public:
int idx, num;
Node () : idx(0), num(0) {}
Node(int i, int n) : idx(i), num(n) {}
};
bool cmp(Node x, Node y) {
return x.num > y.num;
}
int main() {
int n = 10;
Node A[10];
for (int i = 0; i < n; i++) {
cin >> A[i].num;
A[i].idx = i;
}
sort(A, A+n, cmp);
for (int i = 0; i < n; i++) {
cout << A[i].num << " " << A[i].idx << endl;
}
return 0;
}
问题 C: 数组插入数据
这是个很符合链表性质的题目,注意下极大数和极小数即可。
#include<iostream>
#include<climits>
using namespace std;
struct Node {
int x;
Node *nxt;
Node () : x(0), nxt(nullptr) {}
Node (int X) : x(X), nxt(nullptr) {}
};
int main() {
int n = 10;
Node *head = new Node(INT_MIN);
Node *ptr = head;
for (int i = 0; i < n; i++) {
int x; cin >> x;
Node *cur = new Node(x);
ptr->nxt = cur;
ptr = ptr->nxt;
}
int inp;
while (cin >> inp) {
ptr = head; //从头结点开始,满足插入数字极小的情况
for (int i = 0; i <= 10; i++) {
//cout << "----inp: " << inp << ", ptr->x: " << ptr->x << "----" << endl;
if (ptr->nxt != nullptr) {
if (inp >= ptr->x && inp <= ptr->nxt->x) {
Node *cur = new Node(inp);
cur->nxt = ptr->nxt;
ptr->nxt = cur;
break;
}
} else {
if (inp >= ptr->x) {
Node *cur = new Node(inp);
cur->nxt = nullptr;
ptr->nxt = cur;
break;
}
}
ptr = ptr->nxt;
}
ptr = head->nxt; //正常开始从head的下一个
for (int i = 0; i < 10; i++) {
if (i == 9) cout << ptr->x;
else cout << ptr->x << " ";
ptr = ptr->nxt;
}
cout << endl;
}
return 0;
}
问题 D: 字符串操作
主要利用string的四个函数:
- str.insert(index, input)
- str.erase(index, len)
- str.find(target)
- str.replace(idx, len, input)
#include<iostream>
#include<string>
#include<map>
using namespace std;
string cur;
void ADD() {
string inp; int x;
cin >> inp >> x;
cur.insert(x+1, inp);
cout << cur << endl;
}
void DEL() {
int x, n;
cin >> x >> n;
cur.erase(x, n);
cout << cur << endl;
}
void SER() {
string tar;
cin >> tar;
cout << cur.find(tar) << endl;
}
void CHA() {
string inp; int x;
cin >> inp >> x;
cur.replace(x, inp.size(), inp);
cout << cur << endl;
}
int main() {
cin >> cur;
map<string, int> cast;
cast["ADD"] = 0, cast["DEL"] = 1,
cast["SER"] = 2, cast["CHA"] = 3;
string opt;
while (cin >> opt) {
switch (cast[opt]) {
case 0:
ADD(); break;
case 1:
DEL(); break;
case 2:
SER(); break;
case 3:
CHA(); break;
default:
break;
}
}
return 0;
}
第五章
问题 A: 找最高分同学
结构体练习,没有特别要注意的。
#include<iostream>
#include<climits>
using namespace std;
struct Student{
string name;
int score;
Student () : name(""), score(0) {}
Student (string N, int S) : name(N), score(S) {}
};
int main() {
string name;
int score;
Student cur("default", INT_MIN);
while (cin >> name >> score) {
Student A(name, score);
if (A.score > cur.score) cur = A;
}
cout << cur.name;
return 0;
}
问题 B: 输出链表字符
反转链表,主要思路是保存好临时节点,以便逐步遍历。
#include<iostream>
using namespace std;
struct Node {
char x;
Node *next;
Node () : x('\0'), next(nullptr) {}
Node (int X) : x(X), next(nullptr) {}
};
Node *head, *ptr, *frt;
int main() {
string s;
while (cin >> s) {
head = new Node();
ptr = head;
for (char c : s) {
Node *cur = new Node(c);
ptr->next = cur;
ptr = ptr->next;
// cout << "-----" << ptr->x << "-----\n";
}
frt = nullptr;
ptr = head->next;
while (ptr != nullptr) {
Node *tmp = ptr->next;
ptr->next = frt;
frt = ptr;
ptr = tmp;
}
ptr = frt;
while (ptr != nullptr) {
cout << ptr->x;
ptr = ptr->next;
}
cout << endl;
}
return 0;
}
问题 C: 判断形状
相邻边垂直加上相邻边等长,枚举几种可能的点排列方式。
#include<iostream>
#include<cmath>
using namespace std;
struct Node {
int x, y;
Node () : x(0), y(0) {}
Node (int X, int Y) : x(X), y(Y) {}
friend istream& operator >> (istream &in, Node &A) {
in >> A.x >> A.y;
return in;
}
};
inline int dist2(Node A, Node B) {
return (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
}
inline bool JudgeVert(Node P, Node Q, Node S, Node T) {
return (P.x-Q.x)*(S.x-T.x) + (P.y-Q.y)*(S.y-T.y) == 0;
}
//判断 A 为顶点,AB 与 AC 为相邻边
bool Judge(Node A, Node B, Node C, Node D) {
//相邻边垂直
if(!JudgeVert(A, B, A, C)) return false;
//相邻边等长
if(dist2(A, B) != dist2(A, C)) return false;
//第四个点必须合法地成为正方形
//判断 BD 与 CD 是否也是边
return dist2(B, D) == dist2(A, B) && dist2(C, D) == dist2(A, B);
}
string output(bool x) {
return x ? "yes" : "no";
}
int main () {
Node A, B, C, D;
while (cin >> A >> B >> C >> D) {
bool flag =
Judge(A, B, C, D) ||
Judge(A, C, B, D) ||
Judge(A, B, D, C) ||
Judge(A, C, D, B);
cout << output(flag) << endl;
}
return 0;
}
问题 D: 马踏棋盘
最后一题给了个大的,单向BFS甚至会被卡时间。
所以采用双向BFS,vis中1代表从起点经过,2代表从终点经过,两个相遇时把距离相加即可,不过需要考虑一下是否需要加1。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int MAX_DEPTH = 1000;
struct Node {
int x, y;
int step;
Node () : x(0), y(0), step(0) {}
Node (int X, int Y) : x(X), y(Y) {}
Node (int X, int Y, int S) : x(X), y(Y), step(S) {}
bool operator == (Node A) {
return x == A.x && y == A.y;
}
bool check(int m, int n) {
return (x >= 0 && x <= m-1) && (y >= 0 && y <= n-1);
}
friend istream& operator >> (istream &in, Node &A) {
in >> A.x >> A.y;
A.step = 0;
return in;
}
friend ostream& operator << (ostream &out, Node &A) {
out << A.x << " " << A.y << " " << A.step;
return out;
}
};
int vis[505][505];
int mov[8][2] {
{1, 2}, {1, -2}, {-1, 2}, {-1, -2},
{2, 1}, {2, -1}, {-2, 1}, {-2, -1}
};
int main() {
int T;
cin >> T;
while (T--) {
int m, n;
Node start, target;
cin >> m >> n;
cin >> start >> target;
if (start == target) {
cout << 0 << endl;
continue;
}
queue<Node> Q1, Q2;
memset(vis, 0, sizeof(vis));
Q1.push(Node(start.x, start.y, 0));
Q2.push(Node(target.x, target.y, 0));
vis[start.x][start.y] = 1;
vis[target.x][target.y] = 2;
bool flag = false;
int result = 0;
while (!Q1.empty() && !Q2.empty()) {
int size1 = Q1.size();
for (int s = 0; s < size1; s++) {
Node cur = Q1.front(); Q1.pop();
if (cur.step > MAX_DEPTH) {
break;
}
for (int i = 0; i < 8; i++) {
Node nxt(cur.x + mov[i][0], cur.y + mov[i][1], cur.step + 1);
if (nxt.check(m, n)) {
if (vis[nxt.x][nxt.y] == 0) {
vis[nxt.x][nxt.y] = 1;
Q1.push(nxt);
} else if (vis[nxt.x][nxt.y] == 2) {
result = cur.step + nxt.step;
flag = true;
break;
}
}
}
if (flag) break;
}
if (flag) break;
int size2 = Q2.size();
for (int s = 0; s < size2; s++) {
Node cur = Q2.front(); Q2.pop();
if (cur.step > MAX_DEPTH) {
break;
}
for (int i = 0; i < 8; i++) {
Node nxt(cur.x + mov[i][0], cur.y + mov[i][1], cur.step + 1);
if (nxt.check(m, n)) {
if (vis[nxt.x][nxt.y] == 0) {
vis[nxt.x][nxt.y] = 2;
Q2.push(nxt);
} else if (vis[nxt.x][nxt.y] == 1) {
result = nxt.step + cur.step + 1;
flag = true;
break;
}
}
}
if (flag) break;
}
if (flag) break;
}
if (flag) {
cout << result << endl;
} else {
cout << 0 << endl;
}
}
return 0;
}

浙公网安备 33010602011771号