【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;
}
posted @ 2025-12-10 18:21  R4y  阅读(7)  评论(0)    收藏  举报