【华为od】D卷

100

环中最长子串/最长子字符串长度(一)

#include <iostream>

using namespace std;

 string str;
 int n,i = 0;

int main()
{
   
    cin >> str;
   
    while (str[i] != '\0')
    {
        if(str[i] == 'o')
        {
            n ++;
        }
        i ++;
    }
    printf("%d\n", n % 2 ? i - 1 : i);
    return 0;
}
#include <iostream>
#include <string>

class CharacterCounter {
private:
    std::string str;
    int n;
    int i;

public:
    CharacterCounter() : n(0), i(0) {}

    void readInput() {
        std::cin >> str;
    }

    void countCharacters() {
        while (str[i] != '\0') {
            if (str[i] == 'o') {
                n++;
            }
            i++;
        }
    }

    void printResult() const {
        std::cout << (n % 2 ? i - 1 : i) << std::endl;
    }
};

int main() {
    CharacterCounter characterCounter;
    characterCounter.readInput();
    characterCounter.countCharacters();
    characterCounter.printResult();

    return 0;
}

螺旋数字矩阵

#include <iostream>
#include <vector>
using namespace std;

//int res[100][100];
int main()
{
    int nums,n;
    cin >>  nums >> n;
    int m = (nums - 1) / n + 1;
    vector<vector<string>> res(n, vector<string>(m, "*"));
    int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
    
    for(int x = 0, y = 0, d = 0, k = 1; k <= nums; k ++)
    {
        res[x][y] = to_string(k);
        int a = x + dx[d], b = y + dy[d];//a,b表示下一个位置
        if(a < 0 || a >= n || b < 0 || b >= m || res[a][b] != "*")
        {
            d = (d + 1) % 4;
            a = x + dx[d], b = y + dy[d];
        }
        x = a, y = b;
    }
    
    for(int i = 0; i < n; i ++)
    {
        for(int j = 0; j < m; j++) cout << res[i][j] << ' ';
        cout << endl;
    }
    return 0;
}

#include <iostream>
#include <vector>
#include <string>

class SpiralMatrix {
private:
    int nums;
    int n;
    int m;
    std::vector<std::vector<std::string>> res;

public:
    SpiralMatrix() : nums(0), n(0), m(0) {}

    void readInput() {
        std::cin >> nums >> n;
        m = (nums - 1) / n + 1;
        res.resize(n, std::vector<std::string>(m, "*"));
        generateSpiralMatrix();
    }

    void generateSpiralMatrix() {
        int dx[] = {0, 1, 0, -1};
        int dy[] = {1, 0, -1, 0};

        for (int x = 0, y = 0, d = 0, k = 1; k <= nums; k++) {
            res[x][y] = std::to_string(k);
            int a = x + dx[d], b = y + dy[d];

            if (a < 0 || a >= n || b < 0 || b >= m || res[a][b] != "*") {
                d = (d + 1) % 4;
                a = x + dx[d];
                b = y + dy[d];
            }

            x = a;
            y = b;
        }
    }

    void printResult() const {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                std::cout << res[i][j] << ' ';
            }
            std::cout << std::endl;
        }
    }
};

int main() {
    SpiralMatrix spiralMatrix;
    spiralMatrix.readInput();
    spiralMatrix.printResult();

    return 0;
}

最富裕的小家庭

#include <iostream>
#include <vector>
using namespace std;

int n; // 树的节点数
vector<int> a; // 存储每个节点的权值
vector<int> fa; // 存储每个节点的父节点
vector<vector<int>> e; // 存储树的边关系

int main() {
    // 读入节点数
    cin >> n;
    
    // 初始化向量 a,用于存储每个节点的权值
    a.resize(n + 1);
    
    // 读入每个节点的权值
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    // 初始化向量 fa,用于存储每个节点的父节点
    // 初始化向量 e,用于存储树的边关系
    fa.resize(n + 1);
    e.resize(n + 1);

    // 读入树的边关系,构建树结构
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        fa[y] = x; // y 是 x 的子节点,记录父节点信息
        e[x].push_back(y); // 将 y 添加到 x 的子节点列表中
    }

    int ans = 0; // 存储最大权值和

    // 遍历每个节点,计算以当前节点为根的子树的权值和
    for (int i = 1; i <= n; i++) {
        int sum = a[i]; // 初始化 sum 为当前节点的权值
        for (int j = 0; j < e[i].size(); j++) {
            // 将当前节点的每个子节点的权值加到 sum 中
            sum += a[e[i][j]];
        }
        ans = max(ans, sum); // 更新最大权值和
    }

    // 输出结果
    cout << ans << endl;
    return 0;
}


#include <iostream>
#include <vector>

class TreeNode {
public:
    int weight;
    int parent;
    std::vector<int> children;

    TreeNode() : weight(0), parent(0) {}
};

class Tree {
private:
    int n; // 树的节点数
    std::vector<TreeNode> nodes;

public:
    Tree() {}

    void readInput() {
        // 读入节点数
        std::cin >> n;

        // 初始化每个节点
        nodes.resize(n + 1);

        // 读入每个节点的权值
        for (int i = 1; i <= n; i++) {
            std::cin >> nodes[i].weight;
        }

        // 读入树的边关系,构建树结构
        for (int i = 1; i < n; i++) {
            int x, y;
            std::cin >> x >> y;
            nodes[y].parent = x;
            nodes[x].children.push_back(y);
        }
    }

    int calculateMaxWeightSum() const {
        int maxWeightSum = 0;

        // 遍历每个节点,计算以当前节点为根的子树的权值和
        for (int i = 1; i <= n; i++) {
            int sum = nodes[i].weight; // 初始化 sum 为当前节点的权值

            for (int j = 0; j < nodes[i].children.size(); j++) {
                // 将当前节点的每个子节点的权值加到 sum 中
                sum += nodes[nodes[i].children[j]].weight;
            }

            maxWeightSum = std::max(maxWeightSum, sum); // 更新最大权值和
        }

        return maxWeightSum;
    }
};

int main() {
    Tree tree;
    tree.readInput();
    int result = tree.calculateMaxWeightSum();

    // 输出结果
    std::cout << result << std::endl;

    return 0;
}

找座位

#include <bits/stdc++.h>

using namespace std;

int main() {
	
    int res = 0;
	string str;
	cin >> str;

	for (int i = 0; i < str.length(); i++) {
		
		if (str[i] == '0') 
        {  //空位是第一位或左边有空位
			bool left = i == 0 || str[i - 1] == '0';
			// 空位是最后一位或右边有空位
			bool right = i == str.length() - 1 || str[i + 1] == '0';

			// 两者都满足
			if (left && right) {
				res++;
				str[i] = '1';  // 坐一个人
				i++;
			}
		}
	}

	cout << res << endl;

	return 0;
}
#include <iostream>
#include <string>

class SeatingArrangement {
private:
    std::string seating;
    int count;

public:
    SeatingArrangement(const std::string& str) : seating(str), count(0) {}

    void findAndFillEmptySeats() {
        for (int i = 0; i < seating.length(); i++) {
            if (seating[i] == '0') {
                bool left = i == 0 || seating[i - 1] == '0';
                bool right = i == seating.length() - 1 || seating[i + 1] == '0';

                if (left && right) {
                    count++;
                    seating[i] = '1';
                    i++;
                }
            }
        }
    }

    void printResult() const {
        std::cout << count << std::endl;
    }
};

int main() {
    std::string str;
    std::cin >> str;

    SeatingArrangement seatingArrangement(str);
    seatingArrangement.findAndFillEmptySeats();
    seatingArrangement.printResult();

    return 0;
}

密码输入检测

#include <bits/stdc++.h>

using namespace std;

int dx, xx, sz, n;

bool check(string &str)
{
    n = str.size();
    if(n < 8) return false;
    for(auto & ch : str)
    {
        if(ch >= 'a' && ch <= 'z') xx++;
        else if(ch >= 'A' && ch <= 'Z') dx++;
        else if(ch >= '0' && ch <= '9') sz++;

    }
    if(xx >= 1 && dx >= 1 && sz >= 1 && sz + xx + dx < n) return true;
    return false;
}

int main()
{
    string str,res;
    cin >> str;
    for(auto &ch : str)
    {
        if(ch == '<' ) {if(res.size()) res.pop_back();}
        else res.push_back(ch);
    }

    string flag = "false";
    if(check(res)) flag = "true";
    cout << res << ',' << flag << endl;
    return 0;
}
#include <iostream>
#include <string>

class PasswordChecker {
private:
    int dx, xx, sz, n;

public:
    PasswordChecker() : dx(0), xx(0), sz(0), n(0) {}

    bool check(const std::string &str) {
        n = str.size();
        if (n < 8) return false;
        for (auto &ch : str) {
            if (ch >= 'a' && ch <= 'z')
                xx++;
            else if (ch >= 'A' && ch <= 'Z')
                dx++;
            else if (ch >= '0' && ch <= '9')
                sz++;
        }
        if (xx >= 1 && dx >= 1 && sz >= 1 && sz + xx + dx < n) return true;
        return false;
    }

    void processInput() {
        std::string str, res;
        std::cin >> str;
        for (auto &ch : str) {
            if (ch == '<') {
                if (!res.empty()) res.pop_back();
            } else {
                res.push_back(ch);
            }
        }

        std::string flag = "false";
        if (check(res)) flag = "true";
        std::cout << res << ',' << flag << std::endl;
    }
};

int main() {
    PasswordChecker passwordChecker;
    passwordChecker.processInput();
    return 0;
}

分配土地

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <climits>

const int MAX_SIZE = 500;
class Rect {
public:
    int minRow;
    int maxRow;
    int minCol;
    int maxCol;

    Rect() : minRow(INT_MAX), maxRow(INT_MIN), minCol(INT_MAX), maxCol(INT_MIN) {}

    void setRow(int row) {
        minRow = std::min(minRow, row);
        maxRow = std::max(maxRow, row);
    }

    void setCol(int col) {
        minCol = std::min(minCol, col);
        maxCol = std::max(maxCol, col);
    }

    int calculateArea() const {
        return (maxRow - minRow + 1) * (maxCol - minCol + 1);
    }
};

int main() {
    int m, n;
    std::cin >> m >> n;

    std::vector<Rect*> rects(MAX_SIZE, nullptr);

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            int num;
            std::cin >> num;

            if (num > 0) {
                if (rects[num] == nullptr) {
                    rects[num] = new Rect();
                }

                rects[num]->setRow(i);
                rects[num]->setCol(j);
            }
        }
    }

    int maxArea = 0;
    for (int i = 0; i < MAX_SIZE; i++) {
        Rect* rect = rects[i];

        if (rect != nullptr) {
            int area = rect->calculateArea();
            maxArea = std::max(maxArea, area);
            delete rect; // Don't forget to free memory
        }
    }

    std::cout << maxArea << std::endl;

    return 0;
}

#include <iostream>
#include <vector>
#include <climits>

const int MAX_SIZE = 500;

class Rect {
public:
    int minRow;
    int maxRow;
    int minCol;
    int maxCol;

    Rect() : minRow(INT_MAX), maxRow(INT_MIN), minCol(INT_MAX), maxCol(INT_MIN) {}

    void updateBounds(int row, int col) {
        minRow = std::min(minRow, row);
        maxRow = std::max(maxRow, row);
        minCol = std::min(minCol, col);
        maxCol = std::max(maxCol, col);
    }

    int calculateArea() const {
        return (maxRow - minRow + 1) * (maxCol - minCol + 1);
    }
};

class RectanglesAnalyzer {
private:
    std::vector<Rect*> rects;

public:
    RectanglesAnalyzer() : rects(MAX_SIZE, nullptr) {}

    void processInput() {
        int m, n;
        std::cin >> m >> n;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int num;
                std::cin >> num;

                if (num > 0) {
                    if (rects[num] == nullptr) {
                        rects[num] = new Rect();
                    }

                    rects[num]->updateBounds(i, j);
                }
            }
        }
    }

    int calculateMaxArea() const {
        int maxArea = 0;
        for (int i = 0; i < MAX_SIZE; i++) {
            Rect* rect = rects[i];

            if (rect != nullptr) {
                int area = rect->calculateArea();
                maxArea = std::max(maxArea, area);
                delete rect; // Don't forget to free memory
            }
        }

        return maxArea;
    }
};

int main() {
    RectanglesAnalyzer analyzer;
    analyzer.processInput();
    int maxArea = analyzer.calculateMaxArea();
    std::cout << maxArea << std::endl;

    return 0;
}

智能成绩表

#include <bits/stdc++.h>
using namespace std;

int idx;
struct stu
{
    string name;
    vector<int> scores;
};

stu stus[1010];

bool compare(stu& a, stu& b)
{
    if(a.scores[idx] != b.scores[idx])
        return a.scores[idx] > b.scores[idx];
    return a.name < b.name;
}

int main()
{
    string course_names[11];
    int n,m;
    cin >> n >> m;
    for(int i = 0; i < m; i ++) cin >> course_names[i];
    for(int i = 0; i < n; i ++)
    {
        cin >> stus[i].name;
        int sum = 0;
        for(int j = 0; j < m; j ++)
        {
            int score;
            cin >> score;
            stus[i].scores.push_back(score);
            sum += score;
        }
        stus[i].scores.push_back(sum);
    }
    string key;
    cin >> key;
    idx = m;
    for(int i = 0; i < m; i ++)
    {
        if(course_names[i] == key)
        {
            idx = i;
            break;
        }
    }
    sort(stus , stus + n, compare);
    for(int i = 0; i < n; i ++)
    {
        cout << stus[i].name;
        if(i == n) cout << endl;
        else cout << " ";
    }
    return 0;
}

转盘寿司

#include <bits/stdc++.h>

using namespace std;

vector<int> price;
int num;

string str;

int main() {

    getline(cin, str);//获取价格
    stringstream ss(str);//转成数字
    while (ss >> num) {
        price.push_back(num);
    }
    
    int n = price.size();//价格总数
    price.insert(price.end(), price.begin(), price.end());
    
    vector<int> res(n, 0);//赠送的
    stack<int> stk;//单调栈

    for (int i = n * 2 - 1; i >= 0; i--)
    {
        int x = price[i];
        while (stk.size() && x <= stk.top()) stk.pop();
        if (i < n)
        {
            if (stk.empty()) res[i] = 0;
            else res[i] = stk.top();
        }
        stk.push(x);
    }

    for (int i = 0; i < n; i++) {
         cout << res[i] + price[i] << " ";
    }

    return 0;
}

开源项目热度榜单

#include <bits/stdc++.h>

using namespace std;

struct project {
    string name;        // 项目名称
    int hot;            // 项目热度
    string name_lower;  // 项目名称的小写形式
};

const int N = 110;
int n, w[5];
project a[N];//

int main() {
    cin >> n;  // 读取总项目数

    for (int i = 0; i < 5; i++)
        cin >> w[i];  // 读取权重数组

    // 读取每个项目的信息
    for (int i = 0; i < n; i++) {
        string s;
        vector<int> wd(5);

        cin >> s >> wd[0] >> wd[1] >> wd[2] >> wd[3] >> wd[4];

        int hot = 0;

        // 计算项目热度,热度为每个权重乘以对应值的总和
        for (int i = 0; i < 5; i++) {
            hot += wd[i] * w[i];
        }

        string t = s;
        transform(t.begin(), t.end(), t.begin(), ::tolower);  // 将项目名称转换为小写形式
        a[i] = { s, hot, t };
    }

    // 使用 Lambda 表达式进行排序,首先按热度降序,然后按名称升序
    sort(a, a + n, [&](auto& u, auto& wd) 
        {
        if (u.hot != wd.hot) {
            return u.hot > wd.hot;
        }
        return u.name_lower < wd.name_lower;
        });
 
    // 输出排序后的项目名称
    for (int i = 0; i < n; i++)
        cout << a[i].name << endl;

    return 0;
}


提取字符串中的最长合法简单数学表达式

#include <bits/stdc++.h>
#define MAX_N 10000
typedef long long ll;
using namespace std;
ll op,op1,op2,op3;
char sign1, sign2;
char c;
bool is_digit;
string input, maxst, tmp;
queue<char> s_que;
queue<ll> op_que;
ll res;
void updatemaxst(){
    if(tmp.size() > maxst.size()) maxst = tmp;
    tmp = "";
}

int main(){
    cin >> input;
    for(int i = 0; i < input.size(); i++){
        c = input[i];
        if(c == '*' || c == '+' || c == '-'){
            if(i+1 < input.size() && isdigit(input[i+1]) && i-1 >= 0 && isdigit(input[i-1])) tmp += c;
            else updatemaxst();
        }else if(isdigit(c)) tmp += c;
        else updatemaxst();
    }
    updatemaxst();
    // //test maxst
    // cout << maxst << endl;
    for(int i = 0; i < maxst.size(); i++){
        if(isdigit(maxst[i])){
            op *= 10;
            op += maxst[i]-'0';
        }
        else{
            s_que.push(maxst[i]);
            op_que.push(op);
            op = 0;
        }
    }
    op_que.push(op);
    res = op_que.front();
    op_que.pop();
    while(s_que.size()){
        c = s_que.front();
        s_que.pop();
        op1 = op_que.front();
        op_que.pop();
        while(s_que.size() && s_que.front() == '*'){
            s_que.pop();
            op2 = op_que.front();
            op_que.pop();
            op1 *= op2;
        }
        switch(c){
            case '*':
                res *= op1;
                break;
            case '+':
                res += op1;
                break;
            case '-':
                res -= op1;
                break;
        }
    }
    cout << res;
    return 0;
}

机器人搬砖

#include <iostream>
#include <vector>

using namespace std;

vector<int> s; // 保存输入的数组
int x;

int check(vector<int>& w, int mid) 
{
    int res = 0;
    for (int x : w) res += (x + mid - 1) / mid;
    return res;
}

int main() {
    
    while (cin >> x)  s.push_back(x);     
    int n = s.size(); 

    if (n > 8)    cout << -1 << endl; 
    else {
        int l = 1, r = 1e9; 
        while (l < r) {
            int mid = l + r >> 1; 
            if (check(s, mid) <= 8) r = mid; 
            else l = mid + 1; 
        }

        // 输出最终的结果
        cout << r << endl;
    }

    return 0;
}

内存冷热标记

#include<bits/stdc++.h>

using namespace std;

int n,T,x;
unordered_map<int,int> cnt;
vector<int> res;

int main(){

    cin>>n;
    for(int i=0;i<n;i++){
        cin>>x;
        cnt[x]++;
    }
    cin>>T;
    
    for(auto& [a,b]:cnt) if(b >= T) res.push_back(a);
    
    sort(res.begin(),res.end(),[&](int &a,int &b)
    {
        if(cnt[a]!=cnt[b])return cnt[a] > cnt[b];  //按照频率降序排列
        return  a < b;  //按照编号升序排列
    });
    
    cout << res.size() << endl;
    if(res.size())
    for(int& x: res ) cout << x << endl;
    return 0;
}

爱吃蟠桃的孙悟空

#include <bits/stdc++.h>

using namespace std;

vector<int> s; // 保存输入的数组
int H, num;
string str;

int check(vector<int>& m, int mid) 
{
    int res = 0;
    for (int x : m) res += (x + mid - 1) / mid;
    return res;
}

int main() {
    
    getline(cin, str);//获取价格
    stringstream ss(str);//转成数字

    while (ss >> num) {
        s.push_back(num);//
    }

    cin >> H ;

    int n = s.size(); 
    int l = 1, r = 1e9;
    if(n > H) cout << 0 << endl;
    else
    {
        while (l < r) 
        {
            int mid = l + r >> 1; 
            if (check(s, mid) <= H) r = mid; 
            else l = mid + 1; 
        }
        cout << r << endl;
    }
    return 0;
}

虚拟理财游戏

#include <stdio.h>
 
#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
int main() {
    // 产品数, 总投资, 总风险
    int m, n, x;
    scanf("%d %d %d", &m, &n, &x);
 
    // 产品回报率序列
    int back[m];
    for (int i = 0; i < m; i++) scanf("%d", &back[i]);
 
    // 产品风险值序列
    int risk[m];
    for (int i = 0; i < m; i++) scanf("%d", &risk[i]);
 
    // 产品投资额序列
    int invest[m];
    for (int i = 0; i < m; i++) scanf("%d", &invest[i]);
 
    // 记录所选产品的最大投资回报
    int max_invest_back = 0;
 
    // 记录所选产品的序号
    int selectId[] = {-1, -1};
    int selectFee[] = {0, 0};
 
 
    for (int i = 0; i < m; i++) {
        // 如果单个产品的投资风险未超过总风险,则投资单个产品
        if (risk[i] <= x) {
            // 产品I的投资额不能超过该产品的最大投资额,以及总投资
            int investI = MIN(invest[i], n);
            // 产品投资回报
            int invest_back = investI * back[i];
 
            // 如果投资回报高于其他产品组合,那么选择该产品
            if (invest_back > max_invest_back) {
                max_invest_back = invest_back;
                selectId[0] = i;
                selectFee[0] = investI;
 
                selectId[1] = -1;
            }
        } else {
            continue;
        }
 
        for (int j = i + 1; j < m; j++) {
            // 如果两个产品的风险和不超过了总风险,那么两个产品都选
            if (risk[i] + risk[j] <= x) {
                int investI; // 产品I的投资额
                int investJ; // 产品J的投资额
 
                // 其中优先投资回报率大的
                if (back[i] > back[j]) {
                    // 产品I回报率高,则能投多少投多少,最多不能超过min(总投资, 产品I的最多投资额)
                    investI = MIN(n, invest[i]);
                    // 留给产品J的剩余钱未 n - investI, 而产品J最多投资invest[j],因此取二者较小值
                    investJ = MIN(n - investI, invest[j]);
                } else {
                    investJ = MIN(n, invest[j]);
                    investI = MIN(n - investJ, invest[i]);
                }
 
                // 总投资回报
                int invest_back = investI * back[i] + investJ * back[j];
 
                // 如果当前产品组合的总回报更大,则选当前组合产品
                if (invest_back > max_invest_back) {
                    max_invest_back = invest_back;
 
                    selectId[0] = -1;
                    selectId[1] = -1;
 
                    // select的key记录产品的ID,val记录产品的投资额
                    if (investI > 0) {
                        selectId[0] = i;
                        selectFee[0] = investI;
                    }
 
 
                    if (investJ > 0) {
                        selectId[1] = j;
                        selectFee[1] = investJ;
                    }
                }
            }
        }
    }
 
    for (int i = 0; i < m; i++) {
        if(i == selectId[0]) {
            printf("%d", selectFee[0]);
        } else if(i == selectId[1]) {
            printf("%d", selectFee[1]);
        } else {
            printf("%d", 0);
        }
 
        if(i < m - 1) {
            printf(" ");
        }
    }
 
    return 0;
}

游戏分组

#include <iostream>
#include <vector>

using namespace std;

int nums[10];
int total;
int res = 1e9; // 差距最小值
bool choose[10];


void dfs(int cnt, int sum1) 
{
    for (int i = 0; i < 10; i++) {
        if (!choose[i]) {
            choose[i] = true;
            dfs(cnt + 1, sum1 + nums[i]);
            choose[i] = false;
        }
        
    }
    if (cnt == 5) {
        res = min(res, abs(total - 2 * sum1));//取两者之差最小的情况
        return;
    }
}

int main() 
{
    
    for (int i = 0; i < 10; i++) {
        cin >> nums[i];
        total += nums[i];
    }
    dfs(0, 0);//人数,d
    cout << res << endl;

    return 0;
}

围棋的气

#include<iostream>
#include<vector>
#include<string>
#include<sstream>
using namespace std;


vector<vector<int>> g(19, vector<int>(19, 0)); // 创建一个二维数组用于存储棋盘信息
vector<int> b, w;
string input; 
int num;

vector<int> dx = { -1, 1, 0, 0 };
vector<int> dy = { 0, 0, 1, -1 };

int main() {
    
    getline(cin, input); 
    stringstream ss(input); 
    while (ss >> num)  b.push_back(num);
    getline(cin, input);
    stringstream ss2(input);
    while (ss2 >> num)  w.push_back(num);
    
   

    for (int i = 0; i < b.size(); i += 2) 
    { 
        int x = b[i], y = b[i + 1];
        g[x][y] = 1;
    }
    for (int i = 0; i < w.size(); i += 2) 
    { 
        int x = w[i], y = w[i + 1];
        g[x][y] = 2;
    }

    int res1 = 0, res2 = 0; // 创建两个变量用于存储黑棋和白棋的气数量
    for (int i = 0; i < 19; i++) { // 统计黑棋和白棋的气数量
        for (int j = 0; j < 19; j++) {
            if (g[i][j] != 0) continue; // 如果当前位置有棋子,则跳过
            int f1 = 0, f2 = 0; // 创建两个变量用于存储黑棋和白棋的气标记
            for (int dirc = 0; dirc < 4; dirc++) { // 遍历四个方向
                int x = i + dx[dirc], y = j + dy[dirc];
                if (x < 0 || x >= 19 || y < 0 || y >= 19 || g[x][y] == 0) continue; // 如果越界或者没有棋子,跳过
                else if (g[x][y] == 1) f1 = 1; // 如果是黑棋,标记黑棋的气
                else if (g[x][y] == 2) f2 = 1; // 如果是白棋,标记白棋的气
            }
            res1 += f1; // 统计黑棋的气数量
            res2 += f2; // 统计白棋的气数量
        }
    }
    cout << res1 << " " << res2 << " "; // 输出结果
    return 0;
}

万能字符单词拼写、掌握的单词个数

#include<bits/stdc++.h>

using namespace std;
const int N=110;

string words[N], str;
int n, ask, res;
vector<int> cnt(26,0);//存字母个数


bool check(string &s)
{  
    //每次检查初始化str
    auto ch_cnt = cnt;
    int num = ask; 
    for(char &ch : s)
    {
        int m = ch - 'a';
        if( ch_cnt[m] == 0 && num == 0) return false;
        else if( ch_cnt[m]) ch_cnt[m] --;
        else num --;
    }
    return true;
}

int main(){
    
    cin >> n;
    for(int i=0; i < n; i ++) cin >> words[i];
    cin >> str;

    for(auto &ch : str)
    {
        if( ch == '?' ) ask ++;
        else cnt [ ch - 'a' ] ++;
    }
   
    for(int i = 0; i < n; i ++)
        if(check(words[i])) res ++;
    
    cout << res << endl;
    return 0;
}

小明找位置

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

const int N = 10010;
int x,num;
string str;
vector<int> nums;


int main() {

    getline(cin, str);//获取价格
    stringstream ss(str);//转成数字
    while (ss >> num) 
    {
        nums.push_back(num);
        if (ss.peek() == ',') ss.ignore();
    }
    
    cin >> x;
    int l = 0, r = nums.size() - 1;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (nums[mid] >= x) r = mid;
        else l = mid + 1;    
    }

    for (int i = 0; i < nums.size(); i++)
    {
        if (nums[i] >= x) {
            cout << i + 1 << endl;break;}
    }
    return 0;
}


分割均衡字符串

#include<bits/stdc++.h>
using namespace std;

string s;
int res, sum;

int main()
{
    
    cin>>s;
    for(char &ch:s){
        if(ch=='X')sum++;
        else sum--;
        if(sum==0)res++;
    }
    cout<<res<<endl;
    return 0;
}

小华地图寻宝

#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

int m, n, k;
int res = 0;
vector<vector<int>> nums;

// 计算数位和
int get(int num) {
    int sum = 0;
    string s = to_string(num);
    for(char c : s) sum += c - '0';
    return sum;
}

// 深度优先搜索
void dfs(int x, int y) {
    if (x < 0 || x >= n || y < 0 || y >= m || nums[x][y] == 1)    return;
    
    nums[x][y] = 1;
    if (get(x) + get(y) > k)  return;//先写递归基
    
    res++;  // 一般情况
    dfs(x - 1, y);
    dfs(x, y + 1);
    dfs(x + 1, y);
    dfs(x, y - 1);  // 遍历四个方向
}

int main() 
{
    cin >> m >> n >> k;
    nums = vector<vector<int>>(n, vector<int>(m, 0));
    dfs(0, 0);
    cout << res << endl;
    return 0;
}


数的分解

#include <iostream>
#include <cmath>
using namespace std;


int main() {
    long long n;
    cin >> n;
    n *= 2;  // 将问题转化为 2n 的形式,简化计算

    int flag = 1;  // 判断有没有解

    for (int k = 2; k < sqrt(n); k++) 
    {  // 遍历所有可能的 k
        if (n % k != 0) continue;  // 如果 n 不能被 k 整除,则继续下一轮循环
    
        // 判断是否有解
        if ((n / k - (k - 1)) % 2 == 0) {
            int startNum = (n / k - k + 1) / 2;
            cout << n / 2 << "=";

            // 输出等号右边的部分
            for (int x = startNum; x < startNum + k; x++) {
                cout << x;
                if (x != startNum + k - 1) {
                    cout << "+";
                }
            }

            flag = 0;
            break;
        }
    }

    if (flag == 1)     cout << "N" << endl;  // 如果没有解,输出 "N"
    return 0;
}

执行任务赚积分

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>


using namespace std;

typedef pair<int, int> PII;  // 定义对组

const int N = 1E5 + 10;  // 定义常量N

int n, T;  // 定义变量n和T

vector<PII> nums;  // 定义vector数组v

priority_queue<int, vector<int>, greater<int>>heap;  // 定义小根堆

int main()
{
    cin >> n >> T;  
    for (int i = 0; i < n; i++)
    {  
        int a, b;
        cin >> a >> b;//a截至时间,b积分
        nums.push_back({ a,b });  // 将数对加入数组nums
    }
    sort(nums.begin(), nums.end());  // 从小到大排序

    for (int i = 0; i < n; i++) 
    {  
        if (nums[i].first > heap.size()) 
        {  
            if (heap.size() < T) heap.push(nums[i].second); //把积分加进去
            else if (heap.top() < nums[i].second) 
            {  // 如果堆顶的任务比当前任务的值小
                heap.pop();  // 弹出堆顶的任务
                heap.push(nums[i].second);  // 将当前任务加入堆
            }
        }
        else {  // 如果当前任务已经过期
            if (nums[i].second > heap.top()) {  // 如果当前任务的值比堆顶的任务的值大
                heap.pop();  // 弹出堆顶的任务
                heap.push(nums[i].second);  // 将当前任务加入堆
            }
        }
    }
    long long res = 0; 

    for (int i = heap.size();i > 0; i --) 
    {  
        res += heap.top();  // 将堆顶的任务的值加入结果
        heap.pop();  // 弹出堆顶的任务
    }
    cout << res << endl;  // 输出结果
    return 0;  // 返回0
}

计算二又搜索树的高度

#include<iostream>
#include<vector>
using namespace std;
struct Treenode {
	int val;
	Treenode* left;
	Treenode* middle;
	Treenode* right;
};
void insert(Treenode* &root, int num) {  //将值为num的结点插入到以root为根的树中
	if (root == nullptr) {
		Treenode* newNode = new Treenode;
		newNode -> val = num;
		newNode->left = nullptr;
		newNode->middle = nullptr;
		newNode->right = nullptr;
		root = newNode;
	}
	else if (num < root->val - 500)
		return insert(root->left, num);
	else if (num > root->val + 500)
		return insert(root->right, num);
	else
		return insert(root->middle, num);
}

int height(Treenode* root) {
	if (root == nullptr) return 0;
	return max(height(root->left), max(height(root->middle), height(root->right))) + 1;
}
int main() {
	int N;
	cin >> N;
	Treenode* root = nullptr;
	for (int i = 0; i < N; i++) {
		int num;
		cin >> num;
		insert(root, num);
	}
	cout << height(root);
	return 0;
}

API集群负载统计

#include<iostream>
#include<vector>
#include<string>
using namespace std;

int N, Level;
string keyword, url;

int main() 
{
    
    cin >> N;
    vector<string> urls(N);

    
    vector<vector<string>> logs(N, vector<string>());//初始化N个空的一维向量,每个元素存url
    //初始化大小为N的urls,每个url是一个string
    for (int i = 0; i < N; i++) {
        cin >> url;
        urls[i] = url;
    }

    cin >> Level >> keyword;

    // 对含有分隔符的 url 进行处理
    for (int i = 0; i < N; i++) 
    {
        //对每一个url
        string temp = "";
        for (char c : urls[i]) {
            if (c == '/') {
                logs[i].push_back(temp);//logs[i]存url的每个分级
                temp = "";
            }
            else temp += c;
            
        }
        logs[i].push_back(temp);
    }

    int result = 0;
    for (int i = 0; i < N; i++) {
        // 检查 logs[i] 的大小,确保有足够的元素
        if (logs[i].size() - 1 < Level )
            {
            continue;
            }
        if (logs[i][Level] == keyword)
            result++;
    }

    cout << result;
    return 0;
}

剩余银饰的重量

#include <stdio.h>
#include <stdlib.h>
 
#define MAX(a, b) ((a) > (b) ? (a) : (b))
 
int cmp(const void *a, const void *b) {
    return (*(int *) a) - (*(int *) b);
}
 
// 二分查找目标值位置,找不到则返回目标值在数组中有序插入位置
int binarySearch(const int *nums, int nums_size, int target) {
    int low = 0;
    int high = nums_size - 1;
 
    while (low <= high) {
        int mid = (low + high) >> 1;
        int midVal = nums[mid];
 
        if (midVal > target) {
            high = mid - 1;
        } else if (midVal < target) {
            low = mid + 1;
        } else {
            return mid;
        }
    }
 
    return -low - 1;
}
 
int main() {
    // 银饰数组长度
    int n;
    scanf("%d", &n);
 
    // n块银饰的重量
    int weights[n];
    int weights_size = 0;
    while (scanf("%d", &weights[weights_size++])) {
        if (getchar() != ' ') break;
    }
 
    // 升序
    qsort(weights, n, sizeof(int), cmp);
 
    while (weights_size >= 3) {
        // 尾删三个最大值
        int z = weights[weights_size - 1];
        int y = weights[weights_size - 2];
        int x = weights[weights_size - 3];
 
        weights_size -= 3;
 
        // 如果 x == y == z,那么下面公式结果:remain=0, 表示三块银饰完全融掉
        // 如果 x == y && y != z,那么下面公式结果:remain = z - y
        // 如果 x != y && y == z,那么下面公式结果:remain = y - x
        // 如果 x != y && y != z,那么下面公式结果:remain = Math.abs((z - y) - (y - x))
        int remain = abs((z - y) - (y - x));
 
        // 如果还有剩余银块
        if (remain != 0) {
            // 那么就二分查找其在剩余升序weights中的有序插入位置
            int idx = binarySearch(weights, weights_size, remain);
 
            if (idx < 0) {
                idx = -idx - 1;
            }
 
            // 在有序插入位置插入
            for (int i = weights_size - 1; i >= idx; i--) {
                weights[i + 1] = weights[i];
            }
            weights[idx] = remain;
            weights_size++;
        }
    }
 
    if (weights_size == 2) {
        // 如果剩余两块,返回较大的重量(若两块重量相同,返回任意一块皆可)
        printf("%d\n", MAX(weights[0], weights[1]));
    } else if (weights_size == 1) {
        // 如果只剩下一块,返回该块的重量
        printf("%d\n", weights[0]);
    } else {
        // 如果没有剩下,就返回 0
        puts("0");
    }
 
    return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>

class SilverJewelry {
private:
    std::vector<int> weights;

public:
    SilverJewelry() {}

    void readWeights(int n) {
        weights.resize(n);
        for (int i = 0; i < n; ++i) {
            std::cin >> weights[i];
        }
        std::sort(weights.begin(), weights.end());
    }

    int binarySearch(int target) const {
        int low = 0;
        int high = weights.size() - 1;

        while (low <= high) {
            int mid = (low + high) >> 1;
            int midVal = weights[mid];

            if (midVal > target) {
                high = mid - 1;
            } else if (midVal < target) {
                low = mid + 1;
            } else {
                return mid;
            }
        }

        return -low - 1;
    }

    void processWeights() {
        while (weights.size() >= 3) {
            int z = weights.back();
            weights.pop_back();
            int y = weights.back();
            weights.pop_back();
            int x = weights.back();
            weights.pop_back();

            int remain = std::abs((z - y) - (y - x));

            if (remain != 0) {
                int idx = binarySearch(remain);

                if (idx < 0) {
                    idx = -idx - 1;
                }

                weights.insert(weights.begin() + idx, remain);
            }
        }
    }

    int getResult() const {
        if (weights.size() == 2) {
            return std::max(weights[0], weights[1]);
        } else if (weights.size() == 1) {
            return weights[0];
        } else {
            return 0;
        }
    }
};

int main() {
    int n;
    std::cin >> n;

    SilverJewelry silverJewelry;
    silverJewelry.readWeights(n);
    silverJewelry.processWeights();

    std::cout << silverJewelry.getResult() << std::endl;

    return 0;
}
	

最多购买宝石数目

#include <bits/stdc++.h>

using namespace std;

int n,value;


int main() {
    
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; i++) cin >> nums[i];

    cin >> value;

    int res = 0;
    for (int i = 0, j = 0, sum = 0; i < n; i++)
    {
        sum += nums[i];
        while (sum > value)
            sum -= nums[j++];//如果大于价值减去j,然后去到下一个j
        if (sum <= value) res = max(res, i - j + 1);//如果满足条件,把最大值存下
    }
    
    cout << res << endl;
    return 0;
}

连续字母长度(x)

#include<bits/stdc++.h>

using namespace std;

string s;
int k;
vector<int>cnts(26,0);

int main(){
    
    cin>>s;
    cin>>k;

    int n=s.size();
    for(int i = 0, j = 0; j < n; j ++)
    {  
        while( i < n && s[i] == s[j]) i++;  
        int c = s[j] - 'A';
        cnts[c] = max( cnts[c], i - j );
        j = i - 1;
    }
    sort(cnts.begin(),cnts.end(),greater<int>{});  //降序排列 找第k大
    if( k > 26 || cnts[k-1] == 0) puts ("-1");
    else cout << cnts [k-1] << endl;
    return 0;
}


数组连续和

#include <iostream>
#include <vector>

using namespace std;

int n, x;
long long res;

int main() {

    cin >> n >> x;
    vector<int> nums(n);  
    for (int i = 0; i < n; i++) cin >> nums[i];
    if(x == 0 ) cout << n * (n + 1 ) / 2 << endl;
    else
    {
        for (int i = 0, j = 0, sum = 0; i < n; i++)
        {
            sum += nums[i];
            while (sum >= x)
            {
                res += n - i;
                sum -= nums[j++];
            }    
        }
        cout << res << endl;
    }
    return 0;
}


小明的幸运数

#include <stdio.h>
 
#define MAX(a,b) ((a) > (b) ? (a) : (b))
 
int main() {
    int n;
    scanf("%d", &n);
 
    if (n < 1 || n > 100) {
        // 异常情况下输出:12345
        puts("12345");
        return 0;
    }
 
    int m;
    scanf("%d", &m);
    if (m < -100 || m > 100) {
        // 异常情况下输出:12345
        puts("12345");
        return 0;
    }
 
    int pos = 0;
    int maxPos = 0;
 
    for (int i = 0; i < n; i++) {
        int num;
        scanf("%d", &num);
 
        if(num < -100 || num > 100) {
            // 异常情况下输出:12345
            puts("12345");
            return 0;
        }
 
        pos += num;
 
        if(num == m) {
            // 如果某个指令正好和幸运数相等,则小明行进步数+1
            // 注意,如果幸运数字为0,且存在指令为0,那么此时我理解小明应该继续保持不动
            if(num > 0) {
                pos += 1;
            } else if(num < 0) {
                pos -= 1;
            }
        }
 
        // 比较本次移动后的坐标位置和最大坐标位置
        maxPos = MAX(maxPos, pos);
    }
 
    printf("%d\n", maxPos);
 
    return 0;
}
#include <iostream>
#include <limits>

class Movement {
private:
    int n;
    int m;

public:
    Movement() : n(0), m(0) {}

    void readInput() {
        std::cin >> n;

        if (n < 1 || n > 100) {
            // 异常情况下输出:12345
            std::cout << "12345" << std::endl;
            return;
        }

        std::cin >> m;

        if (m < -100 || m > 100) {
            // 异常情况下输出:12345
            std::cout << "12345" << std::endl;
            return;
        }

        processMovements();
    }

    void processMovements() const {
        int pos = 0;
        int maxPos = 0;

        for (int i = 0; i < n; i++) {
            int num;
            std::cin >> num;

            if (num < -100 || num > 100) {
                // 异常情况下输出:12345
                std::cout << "12345" << std::endl;
                return;
            }

            pos += num;

            if (num == m) {
                if (num > 0) {
                    pos += 1;
                } else if (num < 0) {
                    pos -= 1;
                }
            }

            maxPos = std::max(maxPos, pos);
        }

        std::cout << maxPos << std::endl;
    }
};

int main() {
    Movement movement;
    movement.readInput();

    return 0;
}

悄悄话

#include <iostream>
#include <vector>
#include <sstream> // 添加这行

using namespace std;

vector<int> nums;  // 用于存储树节点值的数组
int n, res, num;  // 树的节点数和最大和
string input;

void dfs(int u, int sum) {  // 深度优先搜索函数,接受两个参数:一个节点索引u和从根节点到当前节点的值之和sum
    if (u >= n || nums[u] == -1)  return;//先处理递归姬
    
    res = max(res, sum + nums[u]);  // 更新最大和为当前最大和和当前路径和的最大值
    dfs(2 * u, sum + nums[u]);  // 递归调用dfs函数,处理左子节点
    dfs(2 * u + 1, sum + nums[u]);  // 递归调用dfs函数,处理右子节点
}

int main() {
    
    getline(cin, input);  // 从标准输入读取一行
    stringstream ss(input);  // 使用字符串流处理输入
    nums.push_back(0);  // 在数组开头添加一个虚拟元素,使索引从1开始
    while (ss >> num) nums.push_back(num);  // 将读取的整数存入数组
    n = nums.size();  // 获取数组的长度,即树的节点数

    dfs(1, 0);  
    cout << res << endl;  // 输出最大和

    return 0;
}

CPU算力分配

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;  // 读取第一个整数 n 和第二个整数 m
    vector<int> w1(n), w2(m);

    // 读取第一个数组的元素
    for (int i = 0; i < n; i++) {
        cin >> w1[i];
    }

    // 读取第二个数组的元素
    for (int i = 0; i < m; i++) {
        cin >> w2[i];
    }

    int total_1 = 0, total_2 = 0;

    // 计算第一个数组的总和
    for (int x : w1) {
        total_1 += x;
    }

    // 计算第二个数组的总和
    for (int x : w2) {
        total_2 += x;
    }

    int target = (total_1 - total_2) / 2;  // 计算目标值,即两数组的差值的一半
    set<int> st(w2.begin(), w2.end());  // 使用集合提高查找效率
    sort(w1.begin(), w1.end());  // 对第一个数组进行升序排序

    // 遍历第一个数组,查找符合条件的数对
    for (int x : w1) {
        if (st.count(x - target)) {
            // 输出符合条件的数对并结束循环
            cout << x << " " << x - target << " ";
            break;
        }
    }

    return 0;  // 返回0表示成功执行
}


分披萨(dp盲区)

#include <climits>
#include <iostream>
#include <vector>
using namespace std;
typedef long long LL ;
int n;  // 披萨的数量
vector<LL> a;  // 每块披萨的美味值
vector<vector<LL>> dp;  // 记忆化数组,用于存储已计算过的状态

int solve(LL L, LL R) {
    // “馋嘴“选择一块披萨吃掉,对应端点移动
    if (a[L] > a[R]) {
        L = (L + 1) % n;
    } else {
        R = (R + n - 1) % n;
    }
    // 如果该状态已经计算过,则直接返回结果
    if (dp[L][R] != -1) {
        return dp[L][R];
    }
    // 如果左右端点相同,则说明只剩下一块披萨,直接返回该披萨的美味值
    if (L == R) {
        dp[L][R] = a[L];
    } else {
        // 分别计算选择左边披萨和选择右边披萨的情况下的最大美味值
        dp[L][R] = max(a[L] + solve((L + 1) % n, R), a[R] + solve(L, (R + n - 1) % n));
    }
    return dp[L][R];
}

int main() {
    cin >> n;  // 输入披萨的数量
    a.resize(n);  // 调整披萨美味值数组的大小为n
    dp.assign(n, vector<LL>(n, -1));  // 初始化记忆化数组dp,全部赋值为-1
    for (int i = 0; i < n; i++) {
        cin >> a[i];  // 输入每块披萨的美味值
    }
    LL ans = 0;
    // 枚举吃货第一步取哪块披萨
    for (LL i = 0; i < n; i++) {
        ans = max(ans, solve((i + 1) % n, (i + n - 1) % n) + a[i]);
    }
    cout << ans << endl;  // 输出最多能吃到的披萨的美味值
    return 0;
}

机场航班调度程序

#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>

using namespace std;

string input;
vector<string> str;

int main() {
    //忽略掉逗号模板
    getline(cin, input);
    stringstream ss(input);
    string token;
    while (getline(ss, token, ',')) {
        str.push_back(token);
    }

    sort(str.begin(), str.end());

    // 输出排序后的字符串,使用逗号分隔
    for (size_t i = 0; i < str.size(); ++i) {
        cout << str[i];
        if (i < str.size() - 1) {
            cout << ",";
        }
    }
    cout << endl;

    return 0;
}


攀登者1

#include <stdio.h>
 
#define MAX_SIZE 100000
 
// 算法实现(本题实际考试为核心代码模式,因此考试时只需要写出此函数实现即可)
int getResult(const int heights[], int heights_size) {
    int count = 0;
 
    for (int i = 0; i < heights_size; i++) {
        int leftHeight = i - 1 >= 0 ? heights[i - 1] : 0;
        int rightHeight = i + 1 < heights_size ? heights[i + 1] : 0;
 
        if (heights[i] > leftHeight && heights[i] > rightHeight) {
            count++;
        }
    }
 
    return count;
}
 
// 输入处理
int main() {
    int heights[MAX_SIZE];
    int heights_size = 0;
 
    while (scanf("%d", &heights[heights_size++])) {
        if (getchar() != ',') break;
    }
 
    printf("%d\n", getResult(heights, heights_size));
 
    return 0;
}

生成哈夫曼树(无oj)

#include<bits/stdc++.h>
using namespace std;
typedef pair<long long,long long>PII;
#define x first
#define y second
const int N=1e5+10;
int n,cnt;
struct node{
    long long val,l,r;  //记录当前节点的左节点和右节点,以及当前节点的权值
};
vector<long long>res;  ///记录中序遍历结果
vector<node>g;
void dfs(long long u){  //中序遍历
    if(u==-1)return;
    long long l=g[u].l,r=g[u].r;
    dfs(l);
    res.push_back(g[u].val);
    dfs(r);
}
int main(){
    cin>>n;
    priority_queue<PII,vector<PII>,greater<PII>>heap; //小根堆
    g.resize(n);
    for(long long i=0;i<n;i++){
        long long x;
        cin>>x;
        heap.push({x,i});
        g[i].l=g[i].r=-1;
        g[i].val=x;
    }
    cnt=n;  //新生成的节点编号
    while(heap.size()>1){   //模拟生成哈夫曼树的过程
        auto [x,idx]=heap.top();heap.pop();
        auto [y,idy]=heap.top();heap.pop();
        long long z=x+y,idz=cnt++;
        heap.push({z,idz});
        g.push_back({z,idx,idy});
    }
    dfs(cnt-1);  //从根节点跑一遍中序遍历
    
    for(long long &x:res)cout<<x<<" ";
    return 0;
}

}

密码解密

#include <iostream>
#include <cstring>
#include <sstream>

using namespace std;

string replace(string s, const string& old, const string& new_str) {
    size_t pos = s.find(old);

    while (pos != string::npos) {
        s.replace(pos, old.length(), new_str);
        pos = s.find(old);
    }

    return s;
}

int main() {
    string s;
    getline(cin, s);

    for (int i = 26; i >= 1; i--) {
        string key = to_string(i);

        if (i > 9) {
            key += "*";
        }

        char val = static_cast<char>(97 + i - 1);
        string val_str(1, val);

        s = replace(s, key, val_str);
    }

    cout << s << endl;

    return 0;
}

来自异国的客人

#include <bits/stdc++.h>
using namespace std;
int main(void) {
    int k, n, m;
    cin >> k >> n >> m;
    int ans = 0;
    while (k) {
        ans += k % m == n;
        k /= m;
    }
    cout << ans << endl;
}

求幸存数之和

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 10000
 
int sumOfLeft(int nums[], int nums_size, int jump, int left) {
    // 从起跳点开始的话,需要跳jump+1次,到达需要删除的节点
    // 从起跳点下一个节点开始的话,需要跳jump次,到达需要删除的节点
    // 这里我们从起跳点的下一个节点开始,初始时起跳点为索引0,因此下一个节点为索引1
    int start = 1;
 
    // 如果剩余节点数 > 幸存数量,则还需要继续删除节点
    while (nums_size > left) {
        // 跳 jump 次
        start += jump;
        // 为了避免越界,新起跳点索引位置对剩余节点数取余
        start %= nums_size;
 
        for (int i = start; i < nums_size - 1; i++) {
            nums[i] = nums[i + 1];
        }
        nums_size--;
    }
 
    int sum = 0;
    for (int i = 0; i < nums_size; i++) {
        sum += nums[i];
    }
 
    return sum;
}
 
int main() {
    int nums[MAX_SIZE];
    int nums_size = 0;
 
    while (scanf("%d", &nums[nums_size++])) {
        if (getchar() != ',') break;
    }
 
    int jump;
    scanf("%d", &jump);
 
    int left;
    scanf("%d", &left);
 
    printf("%d\n", sumOfLeft(nums, nums_size, jump, left));
 
    return 0;
}

会议室占用时间

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
 
int rows = 0;
 
int cmp(const void *a, const void *b) {
    return (*(int **) a)[0] - (*(int **) b)[0];
}
 
// 本题实际考试时会核心代码模式,无需处理输入输出,只需要写出merge方法相关实现即可
int **merge(int **roomTimes, int roomTimes_size) {
    // 将各个会议按照开始时间升序
    qsort(roomTimes, roomTimes_size, sizeof(int *), cmp);
 
    // 记录合并后的会议室占用时间段
    int** res = (int**) malloc(sizeof(int*) * roomTimes_size);
 
    // 上一个会议占用时间段
    int* pre = roomTimes[0];
 
    // 当前会议占用时间段
    for(int i=1; i<roomTimes_size; i++) {
        int* cur = roomTimes[i];
 
        if(cur[0] <= pre[1]) {
            // 当前会议开始时间 <= 上一个会议结束时间,则两个会议时间重叠,可以合并
            // 注意合并时,结束时间取两个时间段中较大的结束时间
            if(cur[1] > pre[1]) {
                pre[1] = cur[1];
            }
        } else {
            res[rows++] = pre;
            pre = cur;
        }
    }
 
    res[rows++] = pre;
 
    return res;
}
 
// 输入输出处理
int main() {
    int n;
    scanf("%d", &n);
 
    int **roomTimes = (int **) malloc(sizeof(int *) * n);
    for (int i = 0; i < n; i++) {
        roomTimes[i] = (int *) malloc(sizeof(int) * 2);
        scanf("%d %d", &roomTimes[i][0], &roomTimes[i][1]);
    }
 
    int **res = merge(roomTimes, n);
 
    for (int i = 0; i < rows; i++) {
        printf("%d %d\n", res[i][0], res[i][1]);
    }
 
    return 0;
}

石头剪刀布游戏

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    // 初始化一个包含三个vector的数组
    vector<string> arr[3];

    // 从标准输入中读取数据,直到到达文件末尾
    string s1, s2;
    while (cin >> s1 >> s2) {
        // 将第一个字符串添加到对应的vector中
        arr[s2[0] - 'A'].push_back(s1);
    }

    // 如果三个vector都非空,说明有三种不同的出拳,是平手
    if (all_of(begin(arr), end(arr), [](const vector<string>& lst) { return !lst.empty(); })) {
        cout << "NULL" << endl;
        return 0;
    }

    // 计算空vector的数量
    int num = count_if(begin(arr), end(arr), [](const vector<string>& lst) { return lst.empty(); });

    // 如果有两个或以上的vector为空,说明只有一种出拳,也是平手
    if (num >= 2) {
        cout << "NULL" << endl;
        return 0;
    }

    // 对每个vector进行排序
    for (auto& lst : arr) {
        sort(begin(lst), end(lst));
    }

    int tmp = 0;

    // 找到赢家的索引
    if (arr[0].empty()) {
        tmp = 1;
    } else if (arr[1].empty()) {
        tmp = 2;
    }

    // 输出赢家的出拳方式
    for (const auto& t : arr[tmp]) {
        cout << t << endl;
    }

    return 0;
}

手机App防沉迷系统

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <unordered_set>
using namespace std;

class App {
public:
    string name;
    int p;      // 优先级
    int start;  // 开始时间
    int end;    // 结束时间
};

// 将时间字符串转换为分钟表示
int transTo(string data) {
    string delimiter = ":";
    size_t pos = 0;
    string token;
    int hour, min;
    
    // 提取小时部分
    pos = data.find(delimiter);
    token = data.substr(0, pos);
    hour = stoi(token);
    
    // 提取分钟部分
    token = data.substr(pos + 1, data.length());
    min = stoi(token);
    
    return hour * 60 + min;
}

// 将应用信息字符串转换为 App 对象
App transToApp(string s) {
    string delimiter = " ";
    size_t pos = 0;
    string token;
    string arr[4];
    int i = 0;

    // 使用空格分隔字符串
    while ((pos = s.find(delimiter)) != string::npos) {
        token = s.substr(0, pos);
        arr[i] = token;
        s.erase(0, pos + delimiter.length());
        i++;
    }
    arr[i] = s;

    // 构建 App 对象
    App app;
    app.name = arr[0];
    app.p = stoi(arr[1]);
    app.start = transTo(arr[2]);
    app.end = transTo(arr[3]);

    return app;
}

int main() {
    int n;
    cin >> n;
    cin.ignore();
    App apps[n];
    int cnt = 0;

    // 读取应用信息
    for (int i = 0; i < n; i++) {
        string s;
        getline(cin, s);
        App temp = transToApp(s);
        
        // 如果开始时间晚于结束时间,忽略该应用
        if (temp.start > temp.end) {
            cnt++;
            continue;
        }
        
        apps[i] = transToApp(s);
    }

    n -= cnt;
    vector<App> res;

    // 遍历每个应用
    for (int i = 0; i < n; i++) {
        vector<int> ids;
        
        // 找到与当前应用时间段有重叠的应用
        for (int j = 0; j < res.size(); j++) {
            if (res[j].start <= apps[i].end && apps[i].start <= res[j].end) {
                ids.push_back(j);
            }
        }
        
        int mx = -1;
        
        // 找到重叠应用中优先级最高的
        for (int j = 0; j < ids.size(); j++) {
            mx = max(mx, res[ids[j]].p);
        }
        
        // 如果当前应用优先级更高,则移除重叠应用,添加当前应用
        if (mx < apps[i].p) {
            for (int j = ids.size() - 1; j >= 0; j--) {
                res.erase(res.begin() + ids[j]);
            }
            res.push_back(apps[i]);
        }
    }

    string timeStr;
    getline(cin, timeStr);
    int time = transTo(timeStr);
    string ans = "NA";

    // 查找当前时间所在的应用
    for (int i = 0; i < res.size(); i++) {
        if (res[i].start <= time && time <= res[i].end) {
            ans = res[i].name;
            break;
        }
    }

    cout << ans << endl;  // 输出结果
    return 0;
}


小朋友来自多少小区

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

int main() {
    vector<int> w;
    int num;

    // 输入一行整数,以空格分隔
    while (cin >> num) {
        w.push_back(num);
        if (cin.get() == '\n') break;
    }

    unordered_map<int, int> cnts;
    for (int x : w) {
        cnts[x] = cnts.find(x) != cnts.end() ? cnts[x] + 1 : 1;
    }

    long long ans = 0;
    for (const auto& entry : cnts) {
        int k = entry.first;
        int v = entry.second;
        ans += (v + k) / (k + 1) * (k + 1);
    }

    cout << ans << endl;

    return 0;
}

精准核酸检测

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 100
 
/** 并查集定义 **/
typedef struct {
    int *fa;
} UFS;
 
UFS *new_UFS(int n) {
    UFS *ufs = (UFS *) malloc(sizeof(UFS));
 
    ufs->fa = (int *) malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++) {
        ufs->fa[i] = i;
    }
 
    return ufs;
}
 
int find_UFS(UFS *ufs, int x) {
    if (x != ufs->fa[x]) {
        ufs->fa[x] = find_UFS(ufs, ufs->fa[x]);
        return ufs->fa[x];
    }
    return x;
}
 
void union_UFS(UFS *ufs, int x, int y) {
    int x_fa = find_UFS(ufs, x);
    int y_fa = find_UFS(ufs, y);
 
    if (x_fa != y_fa) {
        ufs->fa[y_fa] = x_fa;
    }
}
 
int main() {
    int n;
    scanf("%d", &n);
 
    int confirmed[MAX_SIZE];
    int confirmed_size = 0;
 
    while (scanf("%d", &confirmed[confirmed_size++])) {
        if (getchar() != ',') break;
    }
 
    UFS *ufs = new_UFS(n);
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int v;
            scanf("%d", &v);
 
            // 有过接触的人进行合并
            if (v == 1) {
                union_UFS(ufs, i, j);
            }
 
            getchar();
        }
    }
 
    // 统计每个接触群体(连通分量)中的人数
    int cnts[MAX_SIZE] = {0};
    for (int i = 0; i < n; i++) {
        int fa = find_UFS(ufs, i);
        cnts[fa]++;
    }
 
    // 记录已统计过的可能感染群体
    int confirmed_fa[MAX_SIZE] = {0};
 
    // 将有感染者的接触群体的人数统计出来
    int ans = 0;
    for (int i = 0; i < confirmed_size; i++) {
        int fa = find_UFS(ufs, confirmed[i]);
 
        // 已统计过的可能感染群体不再统计
        if(confirmed_fa[fa]) continue;
        confirmed_fa[fa] = 1;
 
        ans += cnts[fa];
    }
 
    // 最终需要做核酸的人数,不包括已感染的人
    printf("%d\n", ans - confirmed_size);
 
    return 0;
}

多段线数据压缩

#include <iostream>
#include <vector>

using namespace std;

// 计算两个整数的最大公约数
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

int main() {
    // 存储输入的整数向量
    vector<int> w;
    int num;
    
    // 读取输入并转为整数向量
    while (cin >> num) {
        w.push_back(num);
    }

    // 存储筛选结果的点的坐标向量
    vector<pair<int, int>> res;
    res.push_back({w[0], w[1]});

    int n = w.size();
    for (int i = 2; i < n; i += 2) {
        if (res.size() == 1) {
            res.push_back({w[i], w[i + 1]});
        } else {
            int m = res.size();
            int a = res[m - 1].first - res[m - 2].first;
            int b = res[m - 1].second - res[m - 2].second;
            int g = gcd(abs(a), abs(b));
            int a1 = a / g;
            int b1 = b / g;

            a = w[i] - res[m - 1].first;
            b = w[i + 1] - res[m - 1].second;
            g = gcd(abs(a), abs(b));
            int a2 = a / g;
            int b2 = b / g;

            // 如果两组差值的归一化结果相同,则说明当前点共线,将上一个点弹出,并将当前点加入 res
            if (a1 == a2 && b1 == b2) {
                res.pop_back();
            }
            res.push_back({w[i], w[i + 1]});
        }
    }

    // 打印筛选出的点的坐标
    for (const auto& pair : res) {
        cout << pair.first << " " << pair.second << " ";
    }

    return 0;
}

测试用例执行计划

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;  // 读取输入的整数n和m
    vector<int> a(n + 1);  // 创建整数向量a,长度为n+1
    for (int i = 1; i <= n; i++)
        cin >> a[i];  // 读取n个整数并存入向量a
    vector<vector<int>> list(m, vector<int>());  // 创建整数向量的向量list,长度为m,每个元素为一个空的整数向量
    cin.ignore();  // 忽略换行符
    for (int i = 0; i < m; i++) {
        string s;
        getline(cin, s);  // 读取一行字符串
        istringstream iss(s);  // 创建字符串流
        vector<int> arr((istream_iterator<int>(iss)), istream_iterator<int>());  // 将字符串流转为整数向量arr
        for (int j = 0; j < arr.size(); j++)
            arr[j] = a[arr[j]];  // 将arr中的每个元素替换为向量a中对应索引的值
        int sum = accumulate(arr.begin(), arr.end(), 0);  // 计算arr的和
        list[i].push_back(sum);  // 将和添加到list的第i个元素中
        list[i].push_back(i + 1);  // 将i+1添加到list的第i个元素中
    }
    sort(list.begin(), list.end(), [](const auto &o1, const auto &o2) {  // 对list进行排序
        if (o1[0] != o2[0])
            return o1[0]>o2[0];
        return o1[1] < o2[1];
    });
    for (int i = 0; i < m; i++)
        cout << list[i].back() << endl;  // 输出list的第i个元素的最后一个值
    return 0;
}

堆内存申请

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_COUNT 100
 
typedef struct {
    int offset;  // 内存块起始位置
    int size; // 内存块大小
} Memory;
 
Memory *new_Memory(int offset, int size) {
    Memory *m = (Memory *) malloc(sizeof(Memory));
    m->offset = offset;
    m->size = size;
    return m;
}
 
int cmp(const void *a, const void *b) {
    Memory *A = *((Memory **) a);
    Memory *B = *((Memory **) b);
    return A->offset - B->offset;
}
 
int getResult(int malloc_size, Memory *used_memory[], int used_memory_count) {
    // 申请的内存大小非法,则返回-1
    if (malloc_size <= 0 || malloc_size > 100) {
        return -1;
    }
 
    // 记录最优的申请内存起始位置
    int malloc_offset = -1;
    // 记录最接近申请内存的空闲内存块大小
    int min_malloc_size = 100;
 
    // 对占用的内存按照起始位置升序
    qsort(used_memory, used_memory_count, sizeof(Memory *), cmp);
 
    // 记录(相对于已占用内存的前面一个)空闲内存块的起始位置
    int free_offset = 0;
 
    for (int i = 0; i < used_memory_count; i++) {
        Memory *used = used_memory[i];
 
        // 如果占用的内存起始位置 小于 前面一个空闲内存块起始位置,则存在占用内存区域重叠
        // 如果占用的内存起始位置 大于 99,则非法
        if (used->offset < free_offset || used->offset > 99) return -1;
 
        // 如果占用的内存的大小少于0,则非法
        // 如果占用的内存的大小超过该内存起始位置往后所能申请到的最大内存大小,则无效
        if (used->size <= 0 || used->size > 100 - used->offset) return -1;
 
        // 空闲内存块地址范围是:free_offset ~ memory.offset - 1
        if (used->offset > free_offset) {
            // 空闲内存块大小
            int free_memory_size = used->offset - free_offset;
 
            // 如果该空闲内存块大小足够,且最接近申请的内存大小
            if (free_memory_size >= malloc_size && free_memory_size < min_malloc_size) {
                malloc_offset = free_offset;
                min_malloc_size = free_memory_size;
            }
        }
 
        // 更新:空闲内存的起始位置 = (当前占用内存的结束位置 + 1) = (当前占用内存的起始位置 + 占用大小)
        free_offset = used->offset + used->size;
    }
 
    // 收尾
    int last_free_memory_size = 100 - free_offset;
    if (last_free_memory_size >= malloc_size && last_free_memory_size < min_malloc_size) {
        malloc_offset = free_offset;
    }
 
    return malloc_offset;
}
 
int main() {
    // 要申请的内存大小
    int malloc_size;
    scanf("%d", &malloc_size);
    getchar();
 
    // 已占用的内存
    Memory *used_memory[MAX_COUNT];
    int count = 0;
 
    char s[100];
    while (gets(s)) {
        // 本地测试使用空行作为结束条件
        if(strlen(s) == 0) break;
 
        int offset, size;
        sscanf(s, "%d %d", &offset, &size);
        used_memory[count++] = new_Memory(offset, size);
    }
 
    printf("%d\n", getResult(malloc_size, used_memory, count));
 
    return 0;
}

灰度图存储

#include <stdio.h>
 
int main() {
    int rows, cols;
    scanf("%d %d", &rows, &cols);
 
    int graph[rows * cols];
    int start = 0;
 
    int gray;
    int len;
    while (scanf("%d %d", &gray, &len)) {
        for (int i = start; i < start + len; i++) {
            graph[i] = gray;
        }
 
        start += len;
 
        if (getchar() != ' ') break;
    }
 
    int x, y;
    scanf("%d %d", &x, &y);
 
    printf("%d\n", graph[x * cols + y]);
 
    return 0;
}

火星文计算2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_INPUT_LEN 10000
#define MAX_NUM_LEN 100
 
typedef struct ListNode {
    char ele[MAX_NUM_LEN];
    struct ListNode *prev;
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, char *ele) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    strcpy(node->ele, ele);
    node->prev = NULL;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        node->prev = link->tail;
        link->tail = node;
    }
 
    link->size++;
}
 
char *removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
        link->head->prev = NULL;
    }
 
    link->size--;
 
    char *res = (char *) calloc(MAX_NUM_LEN, sizeof(char));
    strcpy(res, removed->ele);
 
    free(removed);
 
    return res;
}
 
char *removeLast_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->tail;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->tail = link->tail->prev;
        link->tail->next = NULL;
    }
 
    link->size--;
 
    char *res = (char *) calloc(MAX_NUM_LEN, sizeof(char));
    strcpy(res, removed->ele);
 
    free(removed);
 
    return res;
}
 
// 尝试进行#运算
void check(LinkedList *stack, char *operNum2) {
    // 如果栈顶元素是"#"号, 则可以进行#运算
    if (stack->size > 0 && strcmp(stack->tail->ele, "#") == 0) {
        // 取出栈顶的"#"
        removeLast_LinkedList(stack);
        // 取出操作数x
        char *operNum1 = removeLast_LinkedList(stack);
 
        long long x = atoll(operNum1);
        long long y = atoll(operNum2);
 
        // 将4 * x + 3 * y + 2包装为字符串
        char res[MAX_NUM_LEN];
        sprintf(res, "%lld", 4 * x + 3 * y + 2);
 
        // 将计算结果加入栈
        addLast_LinkedList(stack, res);
    } else {
        // 如果栈顶元素不是#,那么操作数2直接入栈
        addLast_LinkedList(stack, operNum2);
    }
}
 
int main() {
    char s[MAX_INPUT_LEN];
    gets(s);
 
    strcat(s, "$"); // 末尾加一个$方便后续收尾处理
 
    LinkedList *stack = new_LinkedList();
 
    // 操作数缓存容器
    char operNum[MAX_NUM_LEN] = {'\0'};
    int operNum_size = 0;
 
    int i = 0;
    while (s[i] != '\0') {
 
        if (s[i] == '#' || s[i] == '$') {
            // 遇到操作符,则尝试进行#运算
            check(stack, operNum);
 
            // 如果s[i]是最后一个字符,即我们手动加到尾部的$,则此时直接结束循环,避免之前添加的收尾$进入stack
            if (s[i + 1] == '\0') break;
 
            // 否则,清空操作数缓存容器
            memset(operNum, '\0', MAX_NUM_LEN);
            operNum_size = 0;
 
            // 将操作符加入栈
            char operator[2];
            sprintf(operator, "%c", s[i]);
            addLast_LinkedList(stack, operator);
        } else {
            // 收集操作数
            operNum[operNum_size++] = s[i];
        }
 
        i++;
    }
 
    // 此时,栈中只会剩下 操作数和$
    // 取出栈底元素作为操作数x
    long long x = atoll(removeFirst_LinkedList(stack));
 
    while (stack->size > 1) {
        // 取出操作符$
        removeFirst_LinkedList(stack);
        // 取出操作数y
        long long y = atoll(removeFirst_LinkedList(stack));
        // 进行$运算,并将运算结果作为新的操作数x
        x = 2 * x + y + 3;
    }
 
    printf("%lld", x);
 
    return 0;
}

求字符串中所有整数的最小和

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_SIZE 10000
 
int main() {
    char s[MAX_SIZE];
    gets(s);
 
    int isNegative = 0;
 
    char negative[MAX_SIZE];
    int negative_size = 0;
 
    long long ans = 0;
    int i = 0;
    while (s[i] != '\0') {
        char c = s[i];
 
        if (c >= '0' && c <= '9') {
            if (isNegative) {
                negative[negative_size++] = c;
            } else {
                ans += c - '0';
            }
        } else {
            if (isNegative && negative_size > 0) {
                ans -= atol(negative);
                memset(negative, '\0', MAX_SIZE);
                negative_size = 0;
            }
 
            isNegative = c == '-';
        }
 
        i++;
    }
 
    if (negative_size > 0) {
        ans -= atol(negative);
    }
 
    printf("%lld\n", ans);
 
    return 0;
}

求满足条件的最长子串的长度

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX(a,b) ((a) > (b) ? (a) : (b))
 
typedef struct ListNode{
    int ele;
    struct ListNode* next;
} ListNode;
 
typedef struct {
    int size;
    ListNode* head;
    ListNode* tail;
} LinkedList;
 
LinkedList* new_LinkedList();
void addLast_LinkedList(LinkedList* link, int ele);
int removeFirst_LinkedList(LinkedList* link);
 
int main() {
    char s[100000];
    gets(s);
 
    int maxLen = -1;
    int hasLetter = 0;
 
    int l = 0;
    int r = 0;
 
    LinkedList* letterIdx = new_LinkedList();
 
    int len = strlen(s);
    while(r < len) {
        char c = s[r];
 
        if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            hasLetter = 1;
            addLast_LinkedList(letterIdx, r);
 
            if(letterIdx->size > 1) {
                l = removeFirst_LinkedList(letterIdx) + 1;
            }
 
            if(r == l) {
                r++;
                continue;
            }
        }
 
        maxLen = MAX(maxLen, r - l + 1);
        r++;
    }
 
    if(!hasLetter) {
        puts("-1");
    } else {
        printf("%d\n", maxLen);
    }
 
 
    return 0;
}
 
LinkedList* new_LinkedList() {
    LinkedList* link = (LinkedList*) malloc(sizeof(LinkedList));
 
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
 
    return link;
}
 
void addLast_LinkedList(LinkedList* link, int ele) {
    ListNode* node = (ListNode*) malloc(sizeof(ListNode));
 
    node->ele = ele;
    node->next = NULL;
 
    if(link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
int removeFirst_LinkedList(LinkedList* link) {
    if(link->size == 0) exit(-1);
 
    ListNode* removed = link->head;
 
    if(link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    int res = removed->ele;
 
    free(removed);
 
    return res;
}

字符串分割(二)(py代码)

# 输入获取
k = int(input())
s = input()
 
 
def convert(s):
    lowerCount = 0
    upperCount = 0
 
    for c in s:
        if 'z' >= c >= 'a':
            lowerCount += 1
        elif 'Z' >= c >= 'A':
            upperCount += 1
 
    if lowerCount > upperCount:
        return s.lower()
    elif lowerCount < upperCount:
        return s.upper()
    else:
        return s
 
 
# 算法入口
def getResult():
    arr = s.split("-")
 
    ans = []
    # ans.append(convert(arr[0])) # 看用例说明,对应第一个子串是不需要做大小写转换的,但是也拿不准,考试时可以都试下
    ans.append(arr[0])
 
    # 剩余子串重新合并为一个新字符串,每k个字符一组
    newStr = "".join(arr[1:])
    for i in range(0, len(newStr), k):
        subStr = newStr[i:i + k]
        # 子串中小写字母居多,则整体转为小写字母,大写字母居多,则整体转为大写字母
        ans.append(convert(subStr))
 
    return "-".join(ans)
 
 
# 算法调用
print(getResult())

英文输入法(py代码)

import re
 
# 输入获取
s = input()
pre = input()
 
 
# 算法入口
def getResult(s, pre):
    tmp = re.split("[^a-zA-Z]", s)
    cache = list(set(tmp))
    cache.sort()
    cache = list(filter(lambda x: x.startswith(pre), cache))
    if len(cache) > 0:
        return " ".join(cache)
    else:
        return pre
 
 
# 算法调用
print(getResult(s, pre))

字符串筛选排序

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s,s1;
    int k;
    cin>>s>>k;
    s1=s;
    sort(s1.begin(),s1.end());   //排序
    int n=s.size();
    k=min(k,n);
    char ch=s1[k-1];  //找到的字符
    for(int i=0;i<n;i++){
        if(s[i]==ch){
            cout<<i<<endl;
            break;
        }
    }
    return 0;
}

连续字母长度

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    int k;
    cin>>s;
    cin>>k;
    vector<int>cnts(26,0);  //统计A~Z连续出现的最大次数
    int n=s.size();
    for(int i=0;i<n;i++){
        int j=i;
        while(j<n&&s[j]==s[i])j++;  //使用双指针找到连续出现的子串
        int c=s[i]-'A';
        cnts[c]=max(cnts[c],j-i);
        i=j-1;
    }
    sort(cnts.begin(),cnts.end(),greater<int>{});  //降序排列 找第k大
    if(k>26||cnts[k-1]==0)puts("-1");
    else cout<<cnts[k-1]<<endl;
    return 0;
}

拼接URL

#include<bits/stdc++.h>
using namespace std;
string s;
int main()
{
    cin>>s;
    string pre,suf;
    bool flag=true;
    for(auto &ch:s){
        if(ch==','){
            flag=false;
            continue;
        }
        else if(flag)pre.push_back(ch);
        else suf.push_back(ch);
    }
    if(!pre.size())pre.push_back('/');  //如果前缀为空 则填充/
    if(!suf.size())suf.push_back('/');  //如果后缀为空 则填充/
    if(pre.back()!='/')pre.push_back('/');  //如果前缀结尾没有/ 则自动补上/
    if(suf[0]!='/')suf='/'+suf;   //如果后缀开头没有/ 则自动补上/
    if(pre.back()=='/'&&suf[0]=='/')pre.pop_back();  //有多余的/ 需要自动去重
    string res=pre+suf;
    cout<<res<<endl;
    return 0;
}

字符串序列判定

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    string t;
    cin >> s;
    cin >> t;
    int n = t.length();
    int now = 0;
    int pos = -1;
    for (int i = 0; i < n; i++) {
        if (t[i] == s[now]) {
            now++;
        }
        if (now == s.length()) {
            pos = i;
            break;
        }
    }
    cout << pos << endl;
    return 0;
}

最长的指定瑕疵度的元音子串

#include <iostream>
#include <string>
#include <vector>
using namespace std;

bool isy(char ch) {  // 判断ch是否为元音字母
    return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
}

int main() {
    int k;
    string s;
    cin >> k >> s;
    vector<bool> f(s.size());  // 判断字符串中每个字符是否为元音,并存储结果到列表 f 中
    for (int i = 0; i < s.size(); i++) {
        f[i] = isy(s[i]);
    }
    int L = 0, R = 0, ans = 0, cnt = 0;  // 初始化双指针 L 和 R,结果 ans,以及辅音个数计数器 cnt
    while (R < s.size()) {
        if (!f[R]) {  // 如果当前字符是辅音
            cnt++;  // 辅音个数加一
        } else {
            while (cnt > k || !f[L]) {  // 当辅音个数大于 k 或者 L 指向的字符是辅音时就将左指针向前移动
                if (!f[L]) {  // 如果 L 移动前指向的字符是辅音,就将计数减一
                    cnt--;
                }
                L++;  // 指针向前移动
            }
            if (cnt == k) {  // 如果辅音个数等于 k,也就是符合题目要求的子串
                ans = max(ans, R-L+1);  // 更新最大长度
            }
        }
        R++;  // R 指针右移
    }
    cout << ans << endl;  // 输出最大长度
    return 0;
}

考勤信息

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

// 定义考勤信息映射
unordered_map<string, int> mp = {{"absent", 0}, {"late", 1}, {"leaveearly", 2}, {"present", 3}};

// 检查考勤信息是否合法的函数
bool check(const vector<string>& s) {
    // 统计每种考勤状态出现的次数
    vector<int> cnts(4, 0);
    int m = s.size();

    // 遍历考勤信息
    for (int i = 0; i < m; i++) {
        // 增加当前考勤状态的计数
        cnts[mp[s[i]]]++;

        // 如果考勤信息长度超过7,减少七天前的考勤状态计数
        if (i > 6) {
            cnts[mp[s[i - 7]]]--;
        }

        // 如果考勤信息长度大于等于7,并且正常上班天数小于4,返回false
        if (i >= 6 && cnts[3] < 4) {
            return false;
        }

        // 如果不是第一个考勤信息,并且连续两天都是迟到或早退,返回false
        if (i > 0 && 1 <= mp[s[i]] && mp[s[i]] <= 2 && 1 <= mp[s[i - 1]] && mp[s[i - 1]] <= 2) {
            return false;
        }
    }

    // 统计所有缺勤的次数
    int count = 0;
    for (const string& x : s) {
        if (mp[x] == 0) {
            count++;
        }
    }

    // 缺勤次数不超过1时返回true,否则返回false
    return count <= 1;
}

int main() {
    int n;
    cin >> n;
    cin.ignore(); // 消耗掉换行符

    // 处理每个测试用例
    while (n--) {
        string line;
        getline(cin, line);
        vector<string> s;

        // 分割字符串得到考勤信息
        size_t pos = 0, next;
        while ((next = line.find(' ', pos)) != string::npos) {
            s.push_back(line.substr(pos, next - pos));
            pos = next + 1;
        }
        s.push_back(line.substr(pos));

        // 调用check函数检查考勤信息是否合法,并输出结果
        if (check(s)) {
            cout << "true" << endl;
        } else {
            cout << "false" << endl;
        }
    }

    return 0;
}

字符串变换最小字符串

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_SIZE 1000
 
char *getResult(char s[]);
 
int main() {
    char s[MAX_SIZE];
    gets(s);
 
    puts(getResult(s));
 
    return 0;
}
 
int cmp(const void *a, const void *b) {
    return (*(char *) a) - (*(char *) b);
}
 
char *getResult(char s[]) {
    int len = strlen(s);
 
    char minS[len + 1];
    strcpy(minS, s);
 
    qsort(minS, len, sizeof(char), cmp);
 
    if (strcmp(minS, s) == 0) {
        return s;
    }
 
    for (int i = 0; i < len; i++) {
        if(s[i] != minS[i]) {
            char tmp = s[i];
            s[i] = minS[i];
 
            int swapIdx = strrchr(s, minS[i]) - s;
            s[swapIdx] = tmp;
            break;
        }
    }
 
    return s;
}

查找接口成功率最优时间段

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_SIZE 100
 
int cmp(const void *a, const void *b) {
    int *A = (int *) a;
    int *B = (int *) b;
    return A[0] - B[0];
}
 
int main() {
    int minAverageLost;
    scanf("%d", &minAverageLost);
 
    int nums[MAX_SIZE];
    int nums_size = 0;
 
    while (scanf("%d", &nums[nums_size++])) {
        if (getchar() != ' ') break;
    }
 
    int preSum[nums_size + 1];
    preSum[0] = 0;
 
    for (int i = 1; i <= nums_size; i++) {
        preSum[i] = preSum[i - 1] + nums[i - 1];
    }
 
    int arrList[MAX_SIZE][2];
    int arrList_size = 0;
 
    int maxLen = 0;
    for (int i = 0; i < nums_size; i++) {
        for (int j = i + 1; j <= nums_size; j++) {
            // sum 是 区间 [i, j-1] 的和
            int sum = preSum[j] - preSum[i];
            int len = j - i;
            int lost = len * minAverageLost;
 
            if (sum <= lost) {
                if (len >= maxLen) {
                    if (len > maxLen) {
                        arrList_size = 0;
                    }
                    arrList[arrList_size][0] = i;
                    arrList[arrList_size][1] = j - 1;
                    arrList_size++;
                    maxLen = len;
                }
            }
        }
    }
 
    if (arrList_size == 0) {
        puts("NULL");
    } else {
        qsort(arrList, arrList_size, sizeof(int *), cmp);
 
        char res[10000];
        for (int i = 0; i < arrList_size; i++) {
            char tmp[100];
            sprintf(tmp, "%d-%d", arrList[i][0], arrList[i][1]);
            strcat(res, tmp);
            strcat(res, " ");
        }
 
        res[strlen(res) - 1] = '\0';
 
        puts(res);
    }
 
    return 0;
}

执行时长

#include <iostream>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    int nums[n];

    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }

    int ans = 0;
    int remain = 0;

    for (int i = 0; i < n; i++) {
        int x = nums[i];
        if (remain + x <= m) {
            remain = 0;
        } else {
            remain += x - m;
        }
        ans++;
    }

    ans += (remain + m - 1) / m; // 上取整
    cout << ans << endl;

    return 0;
}

查找众数及中位数

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int main() {
    vector<int> w;
    int x;
    while (cin >> x) {
        w.push_back(x);
    }

    map<int, int> mp;
    for (int i : w) {
        mp[i]++;
    }

    int maxCnt = 0;
    for (const auto& p : mp) {
        maxCnt = max(maxCnt, p.second);
    }

    vector<int> num;
    for (const auto& p : mp) {
        if (p.second == maxCnt) {
            num.push_back(p.first);
        }
    }

    sort(num.begin(), num.end());
    int n = num.size();
    if (n % 2 == 1) {
        cout << num[n / 2] << endl;
    } else {
        cout << (num[n / 2] + num[n / 2 - 1]) / 2 << endl;
    }

    return 0;
}

最大N个数与最小N个数的和

#include<bits/stdc++.h>
using namespace std;

int main() {
    int m;
    cin >> m;
    vector<int> w(m);
    for (int i = 0; i < m; i++) {
        cin >> w[i];
    }
    int n;
    cin >> n;

    set<int> s(w.begin(), w.end());
    w.assign(s.begin(), s.end());
    sort(w.begin(), w.end());

    m = w.size();

    if (m < 2 * n || w[0] < 0 || w[m - 1] > 1000) {
        cout << -1 << endl;
    } else {
        int result = accumulate(w.begin(), w.begin() + n, 0) +
                     accumulate(w.end() - n, w.end(), 0);
        cout << result << endl;
    }

    return 0;
}

整数对最小和

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
 
int cmp(const void *a, const void *b) {
    return *((int *) a) - *((int *) b);
}
 
int main() {
    int size1;
    scanf("%d", &size1);
 
    int nums1[size1];
    for (int i = 0; i < size1; i++) {
        scanf("%d", &nums1[i]);
    }
 
    int size2;
    scanf("%d", &size2);
 
    int nums2[size2];
    for (int i = 0; i < size2; i++) {
        scanf("%d", &nums2[i]);
    }
 
    int k;
    scanf("%d", &k);
 
    int size = size1 * size2;
 
    int pairs[size];
    int pairs_size = 0;
 
    for (int i = 0; i < size1; i++) {
        for (int j = 0; j < size2; j++) {
            pairs[pairs_size++] = nums1[i] + nums2[j];
        }
    }
 
    qsort(pairs, pairs_size, sizeof(int), cmp);
 
    int sum = 0;
    for (int i = 0; i < k; i++) {
        sum += pairs[i];
    }
 
    printf("%d\n", sum);
 
    return 0;
}

靠谱的车

#include <iostream>
#include <string>
using namespace std;

int main() {
    string w;
    cin >> w;
    int n = w.length();
    long long ans = 0;
    for (int i = 0; i < n; i++) {
        int cost = w[i] - '0';
        if (w[i] > '4') {
            cost -= 1;
        }
        for (int j = n - i - 1; j > 0; j--) {
            cost *= 9;
        }
        ans += cost;
    }
    cout << ans << endl;
    return 0;
}

素数之积

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <math.h>
 
void getResult(int n);
int isPrime(int n);
 
int main() {
    int n;
    scanf("%d", &n);
 
    getResult(n);
 
    return 0;
}
 
void getResult(int n) {
    // 如果n为素数,则必然不可能是两个素数之积
    if (isPrime(n)) {
        puts("-1 -1");
        return;
    }
 
    // 假设i为n的因子
    for (int i = 2; i < n; i++) {
        // 若n不能整除i,则i不是n的因子,继续下次循环,找新的i
        // 若n可以整除i,则i就是n的因子
        if (n % i == 0) {
            // j为n的另一因子
            int j = n / i;
 
            // 只有i,j因子都为素数时,n才是符合题意的素数之积
            if (isPrime(i) && isPrime(j)) {
                // 如果n为两个素数之积,则n只能分解为这两个因子,因为素数无法再次分解出其他因子,也就是说n不再有其他因子了(因子不包含1和自身)
                if (i < j) {
                    printf("%d %d", i, j);
                } else {
                    printf("%d %d", j, i);
                }
                return;
            } else {
                // 如果i,j有一个不是素数因子,则说明n存在非素数因子,此时n不可能是素数之积
                // 如果i,j为相同的素数因子,则n不是满足题意的素数之积
                // 此时可以判定n不符合要求了,直接退出循环
                break;
            }
        }
    }
 
    puts("-1 -1");
}
 
// 判断n是否为素数
int isPrime(int n) {
    if (n <= 3) return n > 1;
 
    if (n % 6 != 1 && n % 6 != 5) {
        return 0;
    }
 
    for (int i = 5; i <= sqrt(n); i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return 0;
        }
    }
 
    return 1;
}

用连续自然数之和来表达整数(py)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 输入获取
t = int(input())
 
 
# 算法入口
def getResult():
    arr = [i + 1 for i in range(t)]
 
    ans = []
 
    l = 0
    r = 1
    total = arr[l]
 
    while l < t:
        if total > t:
            total -= arr[l]
            l += 1
        elif total == t:
            ans.append(arr[l:r])
            total -= arr[l]
            l += 1
            if r >= t:
                break
            else:
                total += arr[r]
                r += 1
        else:
            total += arr[r]
            r += 1
 
    ans.sort(key=lambda x: len(x))
 
    for an in ans:
        print(f"{t}={'+'.join(map(str, an))}")
 
    print(f"Result:{len(ans)}")
 
 
# 算法调用
getResult()

火星文计算(py)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

import re
 
# 输入获取
s = input()
 
 
# 算法入口
def getResult(s):
    p = re.compile("(\\d+)\\$(\\d+)")
 
    while True:
        m = p.search(s)
        if m:
            subS = m.group()
            x = int(m.group(1))
            y = int(m.group(2))
            s = s.replace(subS, str(3 * x + y + 2), 1)  # 注意这里replace只能进行替换第一次出现的,不能替换多次,因此replace方法第三个参数为1,表示只替换首次匹配
        else:
            break
 
    arr = list(map(int, s.split("#")))
 
    x = arr[0]
    for y in arr[1:]:
        x = 2 * x + 3 * y + 4
 
    return x
 
 
# 算法调用
print(getResult(s))

寻找身高相近的小朋友(py)

# 输入获取
h, n = map(int, input().split())
heights = list(map(int, input().split()))
 
 
# 算法入口
def getResult():
    heights.sort(key=lambda x: (abs(x-h), x))
    return " ".join(map(str, heights))
 
 
# 调用算法
print(getResult())

整型数组按个位值排序

#include <bits/stdc++.h>
using namespace std;
int main() {
    string input;
    getline(cin, input);
    vector<pair<string,int>> w;
    size_t pos = 0;
    int cnt = 0;
    while ((pos = input.find(',')) != string::npos) {
        w.push_back({input.substr(0, pos) , cnt++});
        input.erase(0, pos + 1); 
    }
    w.push_back({input , cnt});
    sort(w.begin(), w.end(), [](const pair<string,int>& a, const pair<string,int>& b) {
    	if (a.first.back() != b.first.back()) return a.first.back() < b.first.back();
    	return a.second < b.second;
    });

    for (int i = 0; i < w.size(); i++) {
        cout << w[i].first;
        if (i != w.size() - 1) {
            cout << ",";
        }
    }

    return 0;
}


按身高和体重排队

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct {
    int height;
    int weight;
    int idx;
} Student;
 
int cmp(const void* a, const void* b) {
    Student* A = (Student*) a;
    Student* B = (Student*) b;
 
    return A->height != B->height ? A->height - B->height : A->weight != B->weight ? A->weight - B->weight : A->idx - B->idx;
}
 
int main() {
    int n;
    scanf("%d", &n);
 
    Student students[n];
 
    for(int i=0; i<n; i++) {
        scanf("%d", &students[i].height);
    }
 
    for(int i=0; i<n; i++) {
        scanf("%d", &students[i].weight);
        students[i].idx = i + 1;
    }
 
 
    qsort(students, n, sizeof(Student), cmp);
 
    char res[100000];
 
    for(int i=0; i<n; i++) {
        char tmp[1000];
        sprintf(tmp, "%d", students[i].idx);
 
        strcat(res, tmp);
 
        if(i < n - 1) {
            strcat(res, " ");
        }
    }
 
    puts(res);
 
    return 0;
}

解密犯罪时间(py)

import re
 
reg = re.compile("(([01][0-9])|([2][0-3]))[0-5][0-9]")
 
# 输入获取
hour, minute = input().split(":")
 
 
def dfs(arr, path, res):
    if len(path) == 4:
        timeStr = "".join(path)
        if reg.search(timeStr) is not None:
            res.append(timeStr)
        return
 
    for i in range(len(arr)):
        path.append(arr[i])
        dfs(arr, path, res)
        path.pop()
 
 
# 算法入口
def getResult():
    arr = list(hour)
    arr.extend(list(minute))
 
    arr = list(set(arr))
 
    res = []
    dfs(arr, [], res)
    res.sort()
 
    index = res.index(hour + minute)
 
    if index == len(res) - 1:
        recentTime = res[0]
    else:
        recentTime = res[index + 1]
 
    ans = list(recentTime)
    ans[1] += ":"
    return "".join(ans)
 
 
# 调用算法
print(getResult())

数组连续和

#include <iostream>
#include <vector>

using namespace std;

int n, x;
long long res;

int main() {

    cin >> n >> x;
    vector<int> nums(n);  

    for (int i = 0; i < n; i++) cin >> nums[i];
    if(x == 0 ) cout << n * (n + 1 ) / 2 << endl;
    else
    {
        for (int i = 0, j = 0, sum = 0; i < n; i++)
        {
            sum += nums[i];
            while (sum >= x)
            {
                res += n - i;
                sum -= nums[j++];
            }
            
        }
        cout << res << endl;
    }
    return 0;
}


停车场车辆统计

#include <bits/stdc++.h>
#define MAX_N 10000
using namespace std;
int ct;
bool cur;
int res;
int main(){
    while(scanf("%d",&cur) == 1){
        if(cur == 1){
            ct++;
            if(ct == 3){
                res++;
                ct = 0;
            }
        }else{
            if(ct) res++;
            ct = 0;
        }
        getchar();
    }
    if(ct) res++;
    printf("%d\n",res);
    return 0;
}

绘图机器、计算面积

#include <bits/stdc++.h>
#define y0 yy
#define y1 yyy
typedef long long ll;
using namespace std;
ll x0,x1,y0,dealtay;
ll N,E;
ll res;
int main(){
    scanf("%lld %lld",&N,&E);
    for(int i = 0; i < N; i++){
        scanf("%lld %lld",&x1, &dealtay);
        res += abs(y0)*(x1-x0);
        y0 += dealtay;
        x0 = x1;
    }
    res += abs(y0)*(E-x0);
    printf("%lld\n",res);
    return 0;
}

求最多可以派出多少支团队

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
 
#define MAX(a,b) ((a) > (b) ? (a) : (b))
 
int cmp(const void* a, const void* b) {
    return (*(int*) a) - (*(int*) b);
}
 
int main() {
    int n;
    scanf("%d", &n);
 
    int capacities[n];
    for(int i=0; i<n; i++) {
        scanf("%d", &capacities[i]);
    }
 
    int minCap;
    scanf("%d", &minCap);
 
    // 升序
    qsort(capacities, n, sizeof(int), cmp);
 
    int l = 0;
    int r = n - 1;
 
    // 记录题解
    int ans = 0;
 
    // 单人组队
    while(r >= l && capacities[r] >= minCap) {
        r--;
        ans++;
    }
 
    // 双人组队
    while(l < r) {
        int sum = capacities[l] + capacities[r];
 
        if(sum >= minCap) {
            // 如果两个人的能力值之和>=minCap,则组队
            ans++;
            l++;
            r--;
        } else {
            // 否则将能力低的人剔除,换下一个能力更高的人
            l++;
        }
    }
 
    printf("%d\n", ans);
 
    return 0;
}

找朋友

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> w(n);
    vector<int> res(n);
    stack<int> stk;

    for (int i = 0; i < n; i++) {
        cin >> w[i];
    }

    for (int i = n - 1; i >= 0; i--) {
        while (!stk.empty() && w[stk.top()] <= w[i]) {
            stk.pop();
        }
        if (!stk.empty()) {
            res[i] = stk.top();
        }
        stk.push(i);
    }

    for (int i = 0; i < n; i++) {
        cout << res[i];
        if (i + 1 < n) {
            cout << " ";
        }
    }

    return 0;
}

最长子字符串的长度

#include <stdio.h>
#include <math.h>
 
int main() {
    int m, n;
    scanf("%d %d", &m, &n);
 
    // 记录前车到达终点的时刻,本题后车不可能比前车更早到达,因此如果后车到达时刻 < 前车到达时刻arrived,则后车也是按照前车arrived时刻达到
    double arrived = 0;
 
    for(int i=0; i<m; i++) {
        // 当前车的速度
        double speed;
        scanf("%lf", &speed);
 
        // 当前车到达终点的时刻
        // * 当前车如果比前车更早到达,则被前车阻碍,按前车到达时间算
        // * 当前车如果比前车更晚到达,则不被前车阻碍,按后车到达时间算
        arrived = fmax(arrived, n / speed + i); // n*1.0/speed是行驶花费时间; i是第i辆车的出发时间
    }
 
    // 到达时刻 - 出发时刻 = 路上花费的时间
    double cost = arrived - (m - 1);
 
 
    // 至多保留3个小数位
    char res[100];
    sprintf(res, "%.3f", cost);
 
    // %g 格式 不会打印无效小数位
    printf("%g", atof(res));
 
    return 0;
}

智能驾驶

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
 
#define MAX_SIZE 200
 
// 记录路径中位置的几个状态
typedef struct {
    int x; // 位置横坐标
    int y; // 位置纵坐标
    int init; // 到达此位置所需的最少初始油量
    int remain; // 到达此位置时剩余可用油量
    int flag; // 到达此位置前有没有加过油
} Node;
 
Node *new_Node(int x, int y) {
    Node *node = (Node *) malloc(sizeof(Node));
    node->x = x;
    node->y = y;
    node->init = 0;
    node->remain = 0;
    node->flag = 0;
    return node;
}
 
/** 基于链表实现队列 **/
typedef struct ListNode {
    Node *ele;
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, Node *ele) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->ele = ele;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
Node *removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    return removed->ele;
}
 
// m * n 的地图
int m, n;
// 地图矩阵
int matrix[MAX_SIZE][MAX_SIZE];
 
// 上下左右四个方向对应的偏移量
int offsets[4][2] = {{-1, 0},
                     {1,  0},
                     {0,  -1},
                     {0,  1}};
 
int bfs() {
    // 如果左上角和右下角不可达,则直接返回-1
    if (matrix[0][0] == 0 || matrix[m - 1][n - 1] == 0) {
        return -1;
    }
 
    // 广搜队列
    LinkedList *queue = new_LinkedList();
 
    // 起始位置
    Node *src = new_Node(0, 0);
 
    if (matrix[0][0] == -1) {
        // 如果起始位置就是加油站,则到达(0,0)位置所需初始油量为0,且剩余可用油量为100,且需要标记已加油
        src->init = 0;
        src->remain = 100;
        src->flag = 1;
    } else {
        // 如果起始位置不是加油站,则到达(0,0)位置所需的初始油量至少为matrix[0][0], 剩余可用油量为0,未加油状态
        src->init = matrix[0][0];
        src->remain = 0;
        src->flag = 0;
    }
 
    addLast_LinkedList(queue, src);
 
    // dist_init[x][y] 用于记录起点 (0, 0) 到达 (x, y) 的所有可达路径中最优路径(即初始油量需求最少的路径)的初始油量
    int dist_init[MAX_SIZE][MAX_SIZE];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            // 由于需要记录每个位置的最少需要的初始油量,因此每个位置所需的初始油量初始化为一个较大值
            dist_init[i][j] = INT_MAX;
        }
    }
 
    // dist_remain 用于记录起点 (0,0) 到达 (x,y) 的所有可达路径中最优路径(即初始油量需求最少的路径)的最大剩余可用油量
    // 即如果存在多条最优路径,我们应该选这些路径中到达此位置剩余油量最多的
    int dist_remain[MAX_SIZE][MAX_SIZE] = {0};
 
    // 起点(0,0)到达自身位置(0,0)所需的最少初始油量和最多剩余油量
    dist_init[0][0] = src->init;
    dist_remain[0][0] = src->remain;
 
    // 广搜
    while (queue->size > 0) {
        Node *cur = removeFirst_LinkedList(queue);
 
        // 从当前位置cur开始向上下左右四个方向探路
        for (int i = 0; i < 4; i++) {
            // 新位置
            int newX = cur->x + offsets[i][0];
            int newY = cur->y + offsets[i][1];
 
            // 新位置越界 或者 新位置是障碍,则新位置不可达,继续探索其他方向
            if (newX < 0 || newX >= m || newY < 0 || newY >= n || matrix[newX][newY] == 0) {
                continue;
            }
 
            // 如果新位置可达,则计算到达新位置的三个状态数据
            int init = cur->init; // 到达新位置所需的最少初始油量
            int remain = cur->remain; // 到达新位置时还剩余的最多可用油量
            int flag = cur->flag; // 是否加油了
 
            if (matrix[newX][newY] == -1) {
                // 如果新位置是加油站,则加满油
                remain = 100;
                // 标记加过油了
                flag = 1;
            } else {
                // 如果新位置不是加油站,则需要消耗matrix[newX][newY]个油
                remain -= matrix[newX][newY];
            }
 
            // 如果到达新位置后,剩余油量为负数
            if (remain < 0) {
                if (flag) {
                    // 如果之前已经加过油了,则说明到达此路径前是满油状态,因此我们无法从初始油量里面"借"油
                    continue;
                } else {
                    // 如果之前没有加过油,则超出的油量(-remain),可以从初始油量里面"借",即需要初始油量 init + (-remain) 才能到达新位置
                    init -= remain;
                    // 由于初始油量 init + (-remain) 刚好只能支持汽车到达新位置,因此汽车到达新位置后剩余可用油量为0
                    remain = 0;
                }
            }
 
            // 如果到达新位置所需的初始油量超过了满油100,则无法到达新位置
            if (init > 100) {
                continue;
            }
 
            // 如果可达新位置,则继续检查当前路径策略到达新位置(newX, newY)所需的初始油量init是否比其他路径策略更少
            if (init > dist_init[newX][newY]) {
                // 如果不是,则无需探索新位置(newX, newY)
                continue;
            }
 
            // 当前路径策略到达新位置(newX,newY)所需初始油量init更少,或者,init和前面路径策略相同,但是当前路径策略剩余可用油量remain更多
            if (init < dist_init[newX][newY] || remain > dist_remain[newX][newY]) {
                // 则当前路径策略更优,记录更优路径的状态
                dist_init[newX][newY] = init;
                dist_remain[newX][newY] = remain;
 
                // 将当前新位置加入BFS队列
                Node *next = new_Node(newX, newY);
                next->init = init;
                next->remain = remain;
                next->flag = flag;
 
                addLast_LinkedList(queue, next);
            }
        }
    }
 
    // dist_init[m - 1][n - 1] 记录的是到达右下角终点位置所需的最少初始油量
    if (dist_init[m - 1][n - 1] == INT_MAX) {
        return -1;
    } else {
        return dist_init[m - 1][n - 1];
    }
}
 
int main() {
    scanf("%d,%d", &m, &n);
 
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]);
            getchar();
        }
    }
 
    printf("%d\n", bfs());
 
    return 0;
}

运输时间

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <math.h>
 
int main() {
    int m, n;
    scanf("%d %d", &m, &n);
 
    // 记录前车到达终点的时刻,本题后车不可能比前车更早到达,因此如果后车到达时刻 < 前车到达时刻arrived,则后车也是按照前车arrived时刻达到
    double arrived = 0;
 
    for(int i=0; i<m; i++) {
        // 当前车的速度
        double speed;
        scanf("%lf", &speed);
 
        // 当前车到达终点的时刻
        // * 当前车如果比前车更早到达,则被前车阻碍,按前车到达时间算
        // * 当前车如果比前车更晚到达,则不被前车阻碍,按后车到达时间算
        arrived = fmax(arrived, n / speed + i); // n*1.0/speed是行驶花费时间; i是第i辆车的出发时间
    }
 
    // 到达时刻 - 出发时刻 = 路上花费的时间
    double cost = arrived - (m - 1);
 
 
    // 至多保留3个小数位
    char res[100];
    sprintf(res, "%.3f", cost);
 
    // %g 格式 不会打印无效小数位
    printf("%g", atof(res));
 
    return 0;
}

200

电脑病毒感染

#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>
using namespace std;
struct Edge {
	int destination;  //弧尾编号
	int weight;  //弧的权值
};
int main() {
	int N, link;
	cin >> N >> link;
	vector<vector<Edge>> Graph(N + 1);  //邻接表法存储图
	for (int i = 0; i < link; i++) {  //输入图的各个边
		int u, v, w;
		cin >> u >> v >> w;
		Edge e;
		e.destination = v;
		e.weight = w;
		Graph[u].push_back(e);
	}
	int start;
	cin >> start;
	//使用Dijkstra算法计算
	vector<int> dis(N + 1, INT_MAX);
    dis[start] = 0;
	vector<bool> visit(N + 1, false);
	for (int i = 0; i < N + 1; i++) {
		int u = -1, MIN = INT_MAX;
		for (int j = 0; j < N + 1; j++) {
			if (visit[j] == false && dis[j] < MIN) {
				u = j; 
				MIN = dis[j];
			}
		}
		if (u == -1) {
			continue;
		}
		visit[u] = true;
		for (Edge edge : Graph[u]) {
			int v = edge.destination;
			int w = edge.weight;
			if (dis[u] + w < dis[v]) {
				dis[v] = dis[u] + w;
			}
		}
	}
	
	int result = 0;
	for (int i = 1; i < N + 1; i++) {
		result = max(result, dis[i]);
	}
	if (result < INT_MAX) {
		cout << result;
		return 0;
	}
	else {
		cout << -1;
		return 0;
	}
}

小朋友分组最少调整次数

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 90000
 
typedef struct ListNode {
    int num;
    int count;
    struct ListNode* next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode* head;
    ListNode* tail;
} LinkedList;
 
LinkedList* new_LinkedList() {
    LinkedList* link = (LinkedList*) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addFirst_LinkedList(LinkedList* link, int num, int count) {
    ListNode* node = (ListNode*) malloc(sizeof(ListNode));
    node->num = num;
    node->count = count;
    node->next = NULL;
 
    if(link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        node->next = link->head;
        link->head = node;
    }
 
    link->size++;
}
 
void addLast_LinkedList(LinkedList* link, int num, int count) {
    ListNode* node = (ListNode*) malloc(sizeof(ListNode));
    node->num = num;
    node->count = count;
    node->next = NULL;
 
    if(link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
ListNode* removeFirst_LinkedList(LinkedList* link) {
    if(link->size == 0) exit(-1);
 
    ListNode* removed = link->head;
 
    if(link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    return removed;
}
 
LinkedList* confirm(LinkedList* queue, int confirmed_num) {
    // 此方法用于剔除掉队列中已被调整完位置的小朋友,并且抽离后,尝试合并抽离位置前后的小朋友(如果是同一组)
    // 时间复杂度有点高这里,可能会超时
    LinkedList* back_queue = new_LinkedList();
 
    while (queue->size > 0) {
        ListNode* first = removeFirst_LinkedList(queue);
 
        if(first->num == confirmed_num) {
            continue;
        }
 
        if(back_queue->size == 0 || back_queue->tail->num != first->num) {
            addLast_LinkedList(back_queue, first->num, first->count);
        } else {
            back_queue->tail->count += first->count;
        }
    }
 
    return back_queue;
}
 
 
int main() {
    // 初始小朋友(序号)排队顺序
    int nums[MAX_SIZE];
    int nums_size = 0;
 
    while (scanf("%d", &nums[nums_size++])) {
        if (getchar() != ' ') break;
    }
 
    // 序号->组号 映射关系
    int map[nums_size + 1];
    for (int i = 0; i < nums_size; i++) {
        int num;
        scanf("%d", &num);
 
        map[num] = i / 3;
    }
 
    // 相邻相同组号合并统计
    LinkedList* queue = new_LinkedList();
    for (int i = 0; i < nums_size; i++) {
        int num = map[nums[i]];
 
        if(queue->size == 0 || queue->tail->num != num) {
            addLast_LinkedList(queue, num, 1);
        } else {
            queue->tail->count++;
        }
    }
 
    // 记录调整次数
    int moved_count = 0;
    while(queue->size > 0) {
        ListNode* first = removeFirst_LinkedList(queue);
 
        // 当first.count = 1 时,情况如下
        // 1 x 1 1 y z
        // 1 x 1 y 1 z
        if(first->count == 1) {
            ListNode* x = queue->head;
 
            // 判断x是否存在连续完整分组
            while (x->count == 3) {
                removeFirst_LinkedList(queue);
                x = queue->head;
            }
 
            if(x->num == first->num && x->count == 2) {
                // 情况:1 2 2 2 x[1 1]
                // 将开头1,移动进x中
                moved_count += 1;
                removeFirst_LinkedList(queue);
            } else {
                // 情况如下:
                // 1 x[2 2] 1 1
                // 1 x[2] 1 2 1
                // 将后面的两个1移动到开头
                moved_count += 2;
                queue = confirm(queue, first->num);
            }
        } else if(first->count == 2) {
            // 当first.count == 2 时,情况如下:
            // 1 1 x 1 y z
            moved_count += 1;
            queue = confirm(queue, first->num);
        }
    }
 
    printf("%d\n", moved_count);
 
    return 0;
}

二叉树计算

思路:

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 10000
 
typedef struct TreeNode {
    int num; // 当前节点的值
    int childSum; // 当前节点的左子树+右子树的和
    struct TreeNode *leftChild;
    struct TreeNode *rightChild;
} TreeNode;
 
TreeNode *new_TreeNode(int num) {
    TreeNode *node = (TreeNode *) malloc(sizeof(TreeNode));
    node->num = num;
    node->childSum = 0;
    node->leftChild = NULL;
    node->rightChild = NULL;
    return node;
}
 
// 中序遍历序列
int midOrder[MAX_SIZE];
 
// 前序遍历序列
int preOrder[MAX_SIZE];
 
int cmp(const void *a, const void *b) {
    return *((int *) a) - *((int *) b);
}
 
/**
 * 判断两个子数组是否相同(元素相同,顺序可以不同)
 * @param midL 子数组1的左边界
 * @param preL 子数组2的左边界
 * @param size 子数组的长度
 * @return 子数组1和子数组2是否相同
 */
int notEquals(int midL, int preL, int size) {
    int arr1[size];
    int arr2[size];
    for (int i = 0; i < size; i++) {
        arr1[i] = midOrder[midL + i];
        arr2[i] = preOrder[preL + i];
    }
 
    qsort(arr1, size, sizeof(int), cmp);
    qsort(arr2, size, sizeof(int), cmp);
 
    for (int i = 0; i < size; i++) {
        if (arr1[i] != arr2[i]) {
            return 1;
        }
    }
 
    return 0;
}
 
/**
 * 根据中序遍历序列、前序遍历序列还原树结构
 * @param midL 中序遍历子序列的左边界
 * @param midR 中序遍历子序列的右边界
 * @param preL 前序遍历子序列的左边界
 * @param preR 前序遍历子序列的右边界
 * @return 树结构的根节点
 */
TreeNode *buildTree(int midL, int midR, int preL, int preR) {
    // 某个节点(子树)对应一段子序列,如果对应子序列范围不存在,则子树也不存在
    if (preL > preR) return NULL;
 
    // 先根据前序遍历序列得到根节点,前序序列的首元素就是根节点
    int rootNum = preOrder[preL];
    TreeNode *root = new_TreeNode(rootNum);
 
    // 在中序遍历序列中,找到对应根值的位置,这个位置可能有多个,但是只有一个是正确的
    for (int i = midL; i <= midR; i++) {
        if (midOrder[i] != rootNum) continue;
 
        // 如果中序的左子树,和前序的左子树不同,则对应根值位置不正确
        int leftLen = i - midL;
        if (notEquals(midL, preL + 1, leftLen)) continue;
 
        // 如果中序的右子树,和前序的右子树不同,则对应根值位置不正确
        int rightLen = midR - i;
        if (notEquals(i + 1, preR - rightLen + 1, rightLen)) continue;
 
        // 找到正确根值位置后,开始分治递归处理左子树和右子树
        root->leftChild = buildTree(midL, i - 1, preL + 1, preL + leftLen);
        root->rightChild = buildTree(i + 1, midR, preR - rightLen + 1, preR);
 
        // 记录该节点:左子树+右子树的和(本题新二叉树节点的值)
        root->childSum = (root->leftChild == NULL ? 0 : (root->leftChild->num + root->leftChild->childSum)) +
                         (root->rightChild == NULL ? 0 : (root->rightChild->num + root->rightChild->childSum));
 
        break;
    }
 
    return root;
}
 
// 二叉树中序遍历
void getMidOrder(TreeNode* root) {
    if (root == NULL) return;
 
    // 先遍历左子树
    TreeNode* leftChild = root->leftChild;
    if(leftChild != NULL) {
        getMidOrder(leftChild);
    }
 
    // 再遍历根
    printf("%d ", root->childSum);
 
    // 最后遍历右子树
    TreeNode* rightChild = root->rightChild;
    if(rightChild != NULL) {
        getMidOrder(rightChild);
    }
}
 
int main() {
    int size = 0;
 
    while (scanf("%d", &midOrder[size++])) {
        if (getchar() != ' ') break;
    }
 
    for (int i = 0; i < size; i++) {
        scanf("%d", &preOrder[i]);
    }
 
    // 根据中序序列和前序序列还原树结构
    TreeNode *root = buildTree(0, size - 1, 0, size - 1);
 
    // 打印新的二叉树的的中序遍历序列
    getMidOrder(root);
 
    return 0;
}

分月饼

思路:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int w[N],n,m,res;
void dfs(int u,int sum,int down,int up){  //枚举分给第u个人时,月饼总量还剩下sum 第u个人能分到的最小月饼数量为down 最大月饼数量为up
    if(u==m){
        if(sum==0)res++;
        return;
    }
if(down>sum||sum<0||down>up)return;  //不合法情况
    for(int i=down;i<=up;i++){   //枚举下一个人所获得的月饼数量
        dfs(u+1,sum-i,i,min(sum-i,i+3));
        
    }
    
}
int main(){
    cin>>m>>n;
    dfs(0,n,1,n);
    cout<<res<<endl;
    return 0;
}

最长连续手牌

思路:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

int n;
vector<int> w;
vector<string> color;
vector<int> st;
int res = 0;

void dfs(int cnt, int preNum, const string &preColor) {
    res = max(res, cnt);  // 更新结果变量res
    for (int i = 0; i < n; i++) {
        if (st[i] == 1) {  // 如果当前牌已经被选择
            continue;
        }
        if (preNum == -1 || preNum == w[i] || preColor == color[i]) {  // 满足题目条件
            st[i] = 1;  // 标记当前牌被选择
            dfs(cnt + 1, w[i], color[i]);  // 递归调用dfs函数
            st[i] = 0;  // 取消当前牌的选择
        }
    }
}

int main() {
    string wStr;
    getline(cin, wStr);
    stringstream wStream(wStr);
    int num;
    while (wStream >> num) {
        w.push_back(num);
    }

    string colorStr;
    getline(cin, colorStr);
    stringstream colorStream(colorStr);
    string col;
    while (colorStream >> col) {
        color.push_back(col);
    }

    n = w.size();
    st.resize(n, 0);  // 初始化标记数组

    dfs(0, -1, "");  // 调用dfs函数进行搜索

    cout << res << endl;  // 输出结果

    return 0;
}

5G网络建设

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class UnionFind {
private:
    vector<int> parent;

public:
    UnionFind(int n) {
        parent.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            parent[i] = i;
        }
    }

    int find(int x) {
        if (parent[x] == x) return x;
        return parent[x] = find(parent[x]);
    }

    bool unite(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx == fy) return false;
        parent[fx] = fy;
        return true;
    }
};

int main() {
    int n, m;
    cin >> n >> m; // 读取节点数和边数

    UnionFind uf(n);

    vector<vector<int>> edges;

    for (int i = 1; i <= m; i++) {
        int x, y, z, p;
        cin >> x >> y >> z >> p; // 读取边的起始节点、结束节点、权重和标志

        if (p == 1) uf.unite(x, y); // 如果标志为1,直接合并两个节点
        else {
            edges.push_back({x, y, z}); // 否则将边加入边列表
        }
    }

    // 按边的权重排序
    sort(edges.begin(), edges.end(), [](const vector<int>& a, const vector<int>& b) {
        return a[2] < b[2];
    });

    int ans = 0;
    for (const auto& edge : edges) {
        if (uf.unite(edge[0], edge[1])) ans += edge[2]; // 如果成功合并两个节点,累加权重
    }

    // 判断所有节点是否联通
    bool ok = true;
    for (int i = 2; i <= n; i++) {
        if (uf.find(i) != uf.find(1)) ok = false;
    }

    if (ok) {
        cout << ans << endl; // 如果所有节点联通,输出最小花费
    }
    else {
        cout << -1 << endl; // 否则输出-1
    }

    return 0;
}

攀登者2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
 
#define MAX_SIZE 100000
 
int canClimb[MAX_SIZE] = {0};
int canClimb_count = 0;
 
void climb(const int heights[], int heights_size, int strength, int direction) {
    // 找到第一个地面位置
    int j = 0;
    while (j < heights_size && heights[j] != 0) {
        j++;
    }
 
    int cost = 0; // 攀登体力总消耗(包括上山,下山)
//    int upCost = 0; // 上山体力消耗
//    int downCost = 0; // 下山体力消耗
 
    // 开始攀登
    for (int i = j + 1; i < heights_size; i++) {
        // 如果遇到了新的地面,则从新的地面位置重新计算攀登消耗的体力
        if (heights[i] == 0) {
            cost = 0;
//            upCost = 0;
//            downCost = 0;
            continue;
        }
 
        int diff = heights[i] - heights[i - 1]; // diff记录高度差
 
        if (diff > 0) {
            // 如果过程是上坡
            cost += diff * 3;
//            upCost += diff * 2; // 则上山时,体力消耗 = 高度差 * 2
//            downCost += diff; // 相反的下山时,体力消耗 = 高度差 * 1
 
            // 由于 height[i] > heights[i-1],因此如果 height[i] > heights[i+1] 的话,位置 i 就是山顶
            if (i + 1 >= heights_size || heights[i] > heights[i + 1]) {
                // 计算攀登此山顶的上山下山消耗的体力和
                if (cost < strength) {
//                if (upCost + downCost < strength) {
                    // 需要注意,逆序heights数组后,我们对于的山峰位置需要反转
                    int idx = direction ? i : heights_size - i - 1;
 
                    if(!canClimb[idx]) {
                        // 如果不超过自身体力,则可以攀登
                        canClimb[i] = 1;
                        canClimb_count++;
                    }
                }
            }
 
        } else if (diff < 0) {
            // 如果过程是下坡
            cost -= diff * 3;
//            upCost -= diff; // 则上山时,体力消耗 = 高度差 * 1
//            downCost -= diff * 2; // 相反的下山时,体力消耗 = 高度差 * 2
            // heights[i] < heights[i-1],因此位置i不可能是山顶
        }
    }
}
 
void reverse(int nums[], int nums_size) {
    int i = 0;
    int j = nums_size - 1;
 
    while (i < j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
 
        i++;
        j--;
    }
}
 
// 算法实现(本题实际考试为核心代码模式,因此考试时只需要写出此函数实现即可)
int getResult(int heights[], int heights_size, int strength) {
    climb(heights, heights_size, strength, 1);
 
    reverse(heights, heights_size);
    climb(heights, heights_size, strength, 0);
 
    return canClimb_count;
}
 
// 输入处理
int main() {
    int heights[MAX_SIZE];
    int heights_size = 0;
 
    while (scanf("%d", &heights[heights_size++])) {
        if (getchar() != ',') break;
    }
 
    int strength;
    scanf("%d", &strength);
 
    printf("%d\n", getResult(heights, heights_size, strength));
 
    return 0;
}

园区参观路径(dp)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
 
int main() {
    // 长n -> 行数, 宽m -> 列数
    int n, m;
    scanf("%d %d", &n, &m);
 
    // 地图矩阵,这里把二维压缩为了一维
    int matrix[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 由于matrix是一维数组,所以这里(i, j)二维坐标也要转成一维坐标
            scanf("%d", &matrix[i][j]);
        }
    }
 
    if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
        puts("0");
        return 0;
    }
 
    long dp[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            dp[i][j] = 0;
        }
    }
 
    dp[0][0] = 1;
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (matrix[i][j] == 1) continue;
 
            if (i > 0) {
                dp[i][j] += dp[i - 1][j];
            }
 
            if (j > 0) {
                dp[i][j] += dp[i][j - 1];
            }
        }
    }
 
    printf("%ld\n", dp[n - 1][m - 1]);
 
    return 0;
}

部门人力分配

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


int num, m;
vector<int> nums;

int check(const vector<int>& nums, int m, int x) {

    int cnt = 0;
    int l = 0, r = nums.size() - 1;

    while (l <= r) {
        if (nums[l] + nums[r] <= x) {
            l++;
            r--;
        }
        else r--;
        cnt++;
    }

    return cnt <= m;
}

int main() {

    cin >> m;
   
    while ( cin >> num ) nums.push_back(num);

    sort(nums.begin(), nums.end());

    int n = nums.size();
    int l = nums[n - 1], r = 1e9;

    while (l < r) 
    {
        int mid = l + r >> 1;
        if (check(nums, m, mid)) r = mid;
        else l = mid + 1;
    }

    cout << l << endl;

    return 0;
}

结队编程

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 6000
 
typedef struct Node {
    int idx; // 当前节点的值在原数组中的索引
    int val; // 当前节点的值
    struct Node *left; // 当前节点的左子节点
    struct Node *right; // 当前节点的右子节点
    int count; // 当前节点的左子树中节点数量
} Node;
 
Node *new_Node(int idx, int val) {
    Node *node = (Node *) malloc(sizeof(Node));
    node->idx = idx;
    node->val = val;
    node->left = NULL;
    node->right = NULL;
    node->count = 0;
 
    return node;
}
 
/**
 * 向二叉搜索树中插入新节点
 *
 * @param root (树/子树)根节点
 * @param node 要插入的新节点
 * @param res 数组,其中res[i]代表第i个节点右边比自己小的元素的个数
 * @return 根节点
 */
Node *insertNode(Node *root, Node *node, int res[]) {
    if (root == NULL) {
        return node;
    }
 
    // 由于本题中每个员工有独一无二的职级,即levels中所有元素值都不互相相同,因此这里非大即小
    if (node->val < root->val) {
        // 如果要插入的新节点的值,比根节点小,则插入根节点左子树
        root->count++; // 根节点左子树的节点树+1
        root->left = insertNode(root->left, node, res); // 递归进入左子树继续比较
    } else {
        // 如果要插入的新节点的值,比根节点大,则需要插入根节点的右子树
        res[node->idx] += root->count + 1; // 本处代码原理请看题目解析中的图示
        root->right = insertNode(root->right, node, res); // 递归进入右子树继续比较
    }
 
    return root;
}
 
void reverse(int nums[], int nums_size) {
    int l = 0;
    int r = nums_size - 1;
 
    while (l < r) {
        int tmp = nums[l];
        nums[l] = nums[r];
        nums[r] = tmp;
        l++;
        r--;
    }
}
 
long getResult(int n, int levels[], int levels_size) {
    Node *root = NULL;
 
    // rightSmaller[i] 记录的是 levels[i] 右边比自己小的元素的个数
    int rightSmaller[MAX_SIZE] = {0};
    for (int i = n - 1; i >= 0; i--) {
        root = insertNode(root, new_Node(i, levels[i]), rightSmaller);
    }
 
    reverse(levels, levels_size);
    root = NULL;
 
    // leftSmaller[i] 记录的是 levels[i] 左边比自己小的元素的个数
    int leftSmaller[MAX_SIZE] = {0};
    for (int i = n - 1; i >= 0; i--) {
        root = insertNode(root, new_Node(i, levels[i]), leftSmaller);
    }
    reverse(leftSmaller, levels_size);
 
    // 统计各个元素: 左小 * 右大 + 左大 * 右小
    long sum = 0;
    for (int i = 0; i < n; i++) {
        // 由于本题中每个员工有独一无二的职级,即levels中所有元素值都不互相相同
        int leftSmallerCount = leftSmaller[i];
        // 索引i的左边有 i 个元素,而索引i的左边有leftSmallerCount个比自己小的,因此剩余 i - leftSmallerCount 都是比自己大的
        int leftBiggerCount = i - leftSmallerCount;
 
        int rightSmallerCount = rightSmaller[i];
        // 索引i右边有 n-i-1 个元素,而索引i的右边有rightSmallerCount比自己小的,因此剩余 n-i-1-rightSmallerCount 都是比自己大的
        int rightBiggerCount = n - i - 1 - rightSmallerCount;
 
        sum +=  leftSmallerCount * rightBiggerCount + leftBiggerCount * rightSmallerCount;
    }
 
    return sum;
}
 
int main() {
    int n;
    scanf("%d", &n);
 
    int levels[MAX_SIZE];
    int levels_size = 0;
    while (scanf("%d", &levels[levels_size++])) {
        if (getchar() != ' ') break;
    }
 
    printf("%ld\n", getResult(n, levels, levels_size));
 
    return 0;
}

数据单元的变化替换

#include <stdio.h>
#include <string.h>
 
#define TRUE 1
#define FALSE 0
 
#define MAX_SIZE 26
#define MAX_CELL_CONTENT_LENGTH 110
 
// cells[i]记录每个单元格的内容
char cells[MAX_SIZE][MAX_CELL_CONTENT_LENGTH];
int cells_size = 0;
 
// res记录最后打印结果
char res[MAX_SIZE * MAX_CELL_CONTENT_LENGTH] = {'\0'};
 
int changeCell(int index) {
    // 原始单元格内容
    char *cell = cells[index];
    unsigned long long cell_length = strlen(cell);
 
    // 替换引用后的单元格内容
    char cell_changed[MAX_CELL_CONTENT_LENGTH] = {'\0'};
    unsigned long long cell_changed_length = 0;
 
    int l = 0;
    while (cell[l] != '\0') {
        if (cell[l] != '<') {
            // 非<>中的内容直接记录到cell_changed
            cell_changed[cell_changed_length++] = cell[l++];
            continue;
        }
 
        // 引用单元格编号只能是A~Z的字母,即引用引用字符串长度只能是3,比如"<A>"
        // 因此 l ~ l+2 是引用范围,l指向'<', l+2指向'>', l+1指向单元格编号
        if (cell[l + 2] != '>') {
            return FALSE;
        }
 
        // 引用单元格的编号
        char reference_cell_num = cell[l + 1];
        // 当前单元格的编号
        char self_cell_num = (char) ('A' + index);
 
        // 引用单元格编号只能是A~Z的字母,且不能自引用
        if (reference_cell_num < 'A' || reference_cell_num > 'Z' || reference_cell_num == self_cell_num) {
            return FALSE;
        }
 
        // 引用单元格的数组索引, 'A' -> 0  ... 'Z' -> 25
        int reference_index = reference_cell_num - 'A';
 
        // 引用单元格编号不存在
        if (reference_index >= cells_size) {
            return FALSE;
        }
 
        if (!changeCell(reference_index)) return FALSE;
 
        // 将单元格内容中的引用部分,替换为被引用的单元格的内容
        strcat(cell_changed, cells[reference_index]);
        // 将 “引用” 替换为 “单元格内容”后,更新cell_changed的长度
        cell_changed_length = strlen(cell_changed);
 
        // 将 l 移动到 l+2指向的'>' 后面
        l += 3;
    }
 
    strcpy(cells[index], cell_changed);
 
    return TRUE;
}
 
int main() {
    char s[MAX_SIZE * MAX_CELL_CONTENT_LENGTH];
    scanf("%s", s);
 
    // 按照分隔符","截取输入字符串
    char *token = strtok(s, ",");
    while (token != NULL) {
        strcpy(cells[cells_size++], token);
        token = strtok(NULL, ",");
    }
 
    // 对每个单元格内容进行“引用”替换
    for (int i = 0; i < cells_size; i++) {
        if (!changeCell(i)) {
            // 如果某个单元格"引用"替换失败,则返回"-1"
            puts("-1");
            return 0;
        } else {
            // 否则记录该单元格内容到结果字符串
            strcat(res, cells[i]);
 
            if (i != cells_size - 1) {
                strcat(res, ",");
            }
        }
    }
 
    puts(res);
 
    return 0;
}

高效货运

枚举

#include <iostream>

using namespace std;

int main() {
    int wa, wb, wt, pa, pb;
    cin >> wa >> wb >> wt >> pa >> pb;

    int ans = 0;

    for (int i = 1; i < wt; i++) {
        int a = wa * i; // i 个 A 货物占的容积

        if (a >= wt) {
            break; // 如果超过货车容积,结束循环
        }

        if ((wt - a) % wb == 0) {
            int j = (wt - a) / wb; // 计算运输 B 货物的数量
            ans = max(ans, i * pa + j * pb); // 计算对应的价值,更新答案
        }
    }

    cout << ans << endl;

    return 0;
}


找数字

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    cin >> n;  // 输入一个整数 n
    vector<int> w;

    // 将整数 n 转换为二进制表示,存储到向量 w 中
    while (n) {
        w.push_back(n % 2);
        n /= 2;
    }

    w.push_back(0);  // 在向量末尾添加一个前导0

    int m = w.size();  // 获取向量长度

    // 遍历向量,找到第一个01子串,进行交换操作
    for (int i = 0; i < m; i++) {
        if (i + 1 < m && w[i] == 1 && w[i + 1] == 0) {
            swap(w[i], w[i + 1]);  // 使用 swap 函数交换向量中的元素
            int l = 0, r = i - 1;

            // 将低位中的1全部移动到最低位,0移动到最高位,以保证结果尽可能小
            while (l < r) {
                while (l < r && w[l]) {
                    l++;
                }

                while (l < r && w[r] == 0) {
                    r--;
                }

                if (l < r) {
                    swap(w[l], w[r]);  // 使用 swap 函数交换向量中的元素
                    l++;
                    r--;
                }
            }

            break;  // 跳出循环
        }
    }

    int res = 0;

    // 将二进制向量转换为十进制数
    for (int i = 0; i < m; i++) {
        if (w[i]) {
            res += 1 << i;
        }
    }

    cout << res << endl;  // 输出结果
    return 0;
}

中文分词模拟器(无oj)

#include <bits/stdc++.h>

using namespace std;

string joinString (vector<string> arr , string s){
    string res = "";
    for (auto x : arr){
        res += x;
        res += s;
    }
    return res.substr(0 , res.size() - s.size());
}
// 动态规划求解字符串s是否能被某单词列表组成
// 在有多种拆分情况下,考虑从左到右长度尽量长的单词去切分
string solve(const string& s, const vector<string>& words) {
    int n = s.length();
    vector<bool> f(n + 1, false); // f[i]表示s[i:]这个后缀能被某单词列表组成
    f[n] = true; // 空串能被某单词列表组成

    for (int i = n; i >= 0; i--) { // 从后往前求解
        for (const string& x : words) { // 遍历单词列表
            int m = x.length(); // 单词长度
            if (i + m <= n && s.substr(i, m) == x && f[i + m]) { // 如果s[i : i + m]是单词x且s[i + m:]能被某单词列表组成
                f[i] = true; // 则s[i:]能被某单词列表组成
                break;
            }
        }
    }

    // 接下来考虑如何从f这个动态规划数组中拆出具体方案
    vector<string> res; // 记录分解方式
    if (!f[0]) { // 如果s不能被某单词列表组成, 直接返回本身,用逗号拼接
        string res = "";
        for (auto x : s){
            res += x;
            res += ",";
        }
        return res.substr(0 , res.size() - 1);
    }

    int i = 0;
    // 从前往后求解
    while (i < n) {
        int mx = -1; // 记录从i开始,最长可能的长度,需要满足两个条件: 这个前缀出现在单词中,去掉这个前缀,后缀还是能被组成
        // 遍历单词列表
        for (const string& x : words) {
            // 单词长度
            int m = x.length();
            // 如果s[i : i + m]是单词x且s[i + m:]能被某单词列表组成
            if (i + m <= n && s.substr(i, m) == x && f[i + m]) {
                mx = max(mx, m);
            }
        }
        // 记录分解方式
        res.push_back(s.substr(i, mx));
        i += mx;
    }
    // 返回分解方式
    return joinString(res , ",");
}

int main() {
    string s;
    getline(cin, s);

    string wordsInput;
    getline(cin, wordsInput);
    vector<string> words;
    size_t start = 0;
    size_t end = wordsInput.find(",");
    while (end != std::string::npos) {
        words.push_back(wordsInput.substr(start, end - start));
        start = end + 1;
        end = wordsInput.find(",", start);
    }
    words.push_back(wordsInput.substr(start, end));

    // 对s split先
    vector<string> asks;
    start = 0;
    end = s.find(",");
    while (end != std::string::npos) {
        asks.push_back(s.substr(start, end - start));
        start = end + 1;
        end = s.find(",", start);
    }
    asks.push_back(s.substr(start, end));

    // 一个个单词去dp
    vector<string> res;
    for (const string& x : asks) {
        res.push_back(solve(x, words));
    }
    cout << joinString(res , ",") << endl;
    return 0;
}

符号运算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAX_LENGTH 200
 
// 分数结构
typedef struct Fractions {
    int fa; // 分母
    int ch; // 分子
} Fractions;
 
Fractions *new_Fractions(int fa, int ch) {
    Fractions *fra = (Fractions *) malloc(sizeof(Fractions));
    fra->fa = fa;
    fra->ch = ch;
    return fra;
}
 
// 操作数栈
Fractions *oper_num[MAX_LENGTH];
int oper_num_size = 0;
 
// 操作符栈
char oper_sign[MAX_LENGTH];
int oper_sign_size = 0;
 
// 辗转相除法,求两个数的最大公约数
int getMaxCommonDivisor(int x, int y) {
    while (y != 0) {
        int tmp = y;
        y = x % y;
        x = tmp;
    }
    return x;
}
 
// 取出oper_num栈顶两个操作数进行运算
void calc() {
    // 操作数顺序会对运算产生影响
    Fractions *b = oper_num[--oper_num_size]; // 栈顶元素是运算符右边的操作数
    Fractions *a = oper_num[--oper_num_size]; // 栈顶倒数第二个元素是运算符左边的操作数
 
    // 运算符
    char op = oper_sign[--oper_sign_size];
 
    // 记录运算结果
    Fractions *result = new_Fractions(1, 0);
 
    if (op == '+') {
        result->fa = a->fa * b->fa;
        result->ch = a->ch * b->fa + b->ch * a->fa;
    } else if (op == '-') {
        result->fa = a->fa * b->fa;
        result->ch = a->ch * b->fa - b->ch * a->fa;
    } else if (op == '*') {
        result->fa = a->fa * b->fa;
        result->ch = a->ch * b->ch;
    } else if (op == '/') {
        result->fa = a->fa * b->ch;
        result->ch = a->ch * b->fa;
    }
 
    oper_num[oper_num_size++] = result;
}
 
int main() {
    char s[MAX_LENGTH];
    gets(s);
 
    // +,-,*,/ 运算符优先级
    int priority[128] = {0};
    priority['+'] = 1;
    priority['-'] = 1;
    priority['*'] = 2;
    priority['/'] = 2;
 
    // 操作数的字符缓存容器
    char numStr[MAX_LENGTH] = {'\0'};
    int numStr_size = 0;
 
    int i = 0;
    while (s[i] != '\0') {
        char c = s[i];
 
        // 遇到数字字符
        if (c >= '0' && c <= '9') {
            // 则将该数字所在操作数的剩余数字字符一次性探索完
            while (c >= '0' && c <= '9') {
                numStr[numStr_size++] = c;
                if (s[i + 1] == '\0') break;
                i++;
                c = s[i];
            }
 
            // 探索完后,将操作数缓存容器中记录的字符,变为分数后,压入操作数栈
            oper_num[oper_num_size++] = new_Fractions(1, atoi(numStr));
            // 注意清空操作数缓存容器
            memset(numStr, '\0', MAX_LENGTH);
            numStr_size = 0;
        }
 
        // 遇到运算符
        if (c == '+' || c == '-' || c == '*' || c == '/') {
            // 只要栈顶运算符的优先级 >= 当前运算符,就需要不停出栈运算
            while (oper_sign_size > 0 && oper_sign[oper_sign_size - 1] != '(' &&
                priority[c] <= priority[oper_sign[oper_sign_size - 1]]) {
                calc();
            }
            oper_sign[oper_sign_size++] = c;
        } else if (c == ')') {
            // 遇到')', 需要将操作符栈中靠近栈顶的'('后面的运算都出栈做了
            while (oper_sign[oper_sign_size - 1] != '(') {
                calc();
            }
            // 最后将')'对应的'('出栈
            oper_sign_size--;
        } else if (c == '(') {
            // 遇到'(',则直接压倒操作符栈
            oper_sign[oper_sign_size++] = c;
        }
 
        i++;
    }
 
    // oper_num栈中还有2个以上的数,则还需要进行运算
    while (oper_num_size > 1) {
        calc();
    }
 
    // oper_num栈中只剩一个数时,该数就是表达式结果
    Fractions *result = oper_num[--oper_num_size];
 
    // 如果结果的分母为0(除数为0),则不合法
    if (result->fa == 0) {
        puts("ERROR");
        return 0;
    }
 
    // 求分子、分母的最大公约数,并进行约份,求得最简格式的分子,分母
    int k = getMaxCommonDivisor(result->fa, result->ch);
    result->fa /= k;
    result->ch /= k;
 
    // 求计算结果的符号,这里用乘法是为了避免 分母小,分子大,除法结果为0的情况,这样会丢失符号信息
    if (result->fa * result->ch < 0) {
        printf("-");
    }
 
    int fa = abs(result->fa);
    int ch = abs(result->ch);
 
    if (fa == 1) {
        // 如果分母为1,则直接输出分子
        printf("%d\n", ch);
    } else {
        // 如果分母不为1,则输出 分子 / 分母
        printf("%d/%d\n", ch, fa);
    }
 
    return 0;
}

根据IP查找城市

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
 
#define CITY_NAME_LENGTH 100
#define CITY_LIST_LENGTH 500000
#define QUERY_LIST_LENGTH 700000
 
typedef struct Range {
    char city[CITY_NAME_LENGTH];
    long startIpDec;
    long endIpDec;
    long ipLen;
} Range;
 
// IP地址转整型
long ip2dec(char *ip) {
    long res = 0;
 
    int n1, n2, n3, n4;
    sscanf(ip, "%d.%d.%d.%d", &n1, &n2, &n3, &n4);
 
    res = n1 | (res << 8);
    res = n2 | (res << 8);
    res = n3 | (res << 8);
    res = n4 | (res << 8);
 
    return res;
}
 
Range *new_Range(char *city, char *startIpStr, char *endIpStr) {
    Range *range = (Range *) malloc(sizeof(Range));
    strcpy(range->city, city);
    range->startIpDec = ip2dec(startIpStr);
    range->endIpDec = ip2dec(endIpStr);
    range->ipLen = range->endIpDec - range->startIpDec + 1;
    return range;
}
 
// 第一行输入
char s1[CITY_LIST_LENGTH];
 
// 第二行输入
char s2[QUERY_LIST_LENGTH];
 
 
Range *ranges[CITY_LIST_LENGTH];
int ranges_size = 0;
 
int main() {
    gets(s1);
 
    char *token1 = strtok(s1, ";");
    while (token1 != NULL) {
        // 提取各个城市IP列表信息
        char city[CITY_NAME_LENGTH] = {'\0'};
        char startIpStr[10] = {'\0'};
        char endIpStr[10] = {'\0'};
 
        sscanf(token1, "%[^=]=%[^,],%[^,]", city, startIpStr, endIpStr);
        ranges[ranges_size++] = new_Range(city, startIpStr, endIpStr);
 
        token1 = strtok(NULL, ";");
    }
 
 
    gets(s2);
 
    // 遍历待查询的IP地址
    char *token2 = strtok(s2, ",");
    while (token2 != NULL) {
        long ipDec = ip2dec(token2);
 
        // 记录该目标IP地址的最佳匹配城市
        char *city = "";
        // 记录最佳匹配城市IP段的长度
        long minLen = LONG_MAX;
 
        // 将带查询IP与城市IP段列表逐一匹配
        for (int i = 0; i < ranges_size; i++) {
            // 如果带查询的IP地址 在某城市的IP段范围内,且该城市的IP段长度更小,则该城市为待查询IP的最佳匹配城市
            if (ipDec >= ranges[i]->startIpDec && ipDec <= ranges[i]->endIpDec && minLen > ranges[i]->ipLen) {
                city = ranges[i]->city;
                minLen = ranges[i]->ipLen;
            }
        }
 
        printf("%s", city);
 
        token2 = strtok(NULL, ",");
 
        if(token2 != NULL) {
            printf(",");
        }
    }
 
    return 0;
}

文件缓存系统(py)

# 双向链表节点
class Node:
    def __init__(self, key, val, freq):
        """
        :param key: 记录本题的键
        :param val: 记录本题的值
        :param freq: 记录该键被访问的次数
        """
        self.key = key
        self.val = val
        self.freq = freq
        self.prev = None
        self.next = None
 
 
# 双向链表
class Link:
    def __init__(self):
        self.size = 0
        self.head = None
        self.tail = None
 
    def addLast(self, node):
        """
        尾插
        :param node: 要被插入的节点
        """
        if self.size == 0:
            # 空链表,则node节点插入后,即为头、尾节点
            self.head = node
            self.tail = node
        else:
            # 非空链表,则node节点插入到tail节点后面
            self.tail.next = node
            node.prev = self.tail
            self.tail = node
 
        self.size += 1
 
    def remove(self, node):
        """
        删除指定节点
        :param node: 要删除的节点
        """
        if self.size == 0:
            # 空链表没有节点,所以无法删除
            return
 
        if self.size == 1:
            # 链表只有一个节点,则删除完后,变为空链表
            self.head = None
            self.tail = None
        elif self.head == node:
            # 如果要删除的节点是头节点
            self.head = self.head.next
            self.head.prev = None
        elif self.tail == node:
            # 如果要删除的节点是尾节点
            self.tail = self.tail.prev
            self.tail.next = None
        else:
            # 如果要删除的节点是中间节点
            node.prev.next = node.next
            node.next.prev = node.prev
 
        self.size -= 1
 
 
# LFU缓存
class LFUCache:
    def __init__(self, capacity):
        self.keyMap = {}  # keyMap用于记录key对应的node
        self.freqMap = {}  # freqMap的key是访问次数,value是具有相同访问次数的key对应的node组成的链表,链表头是最远访问的,链表尾是最近访问的
        self.capacity = capacity  # LFU缓存中能记录的最多key的数量
        self.minFreq = 0  # LFU缓存中所有的key中最少的访问次数
 
    def get(self, key):
        # 如果文件不存在,则不作任何操作。
        if key not in self.keyMap:
            return
 
        # 每次文件访问后,总访问次数加1,最近访问时间更新到最新时间
        node = self.keyMap[key]
        self.incNodeFreq(node)
 
    def put(self, key, val):
        # 如果新文件的文件名和文件缓存中已有的文件名相同,则不会放在缓存中
        if key in self.keyMap:
            return
 
        # 当缓存空间不足以存放新的文件时,根据规则删除文件,直到剩余空间满足新的文件大小位置,再存放新文件。
        while self.capacity < val:
            if self.minFreq == 0:
                # 文件系统空了,也放不下该文件,则不放入
                return
 
            # 找出最少访问次数对应的链表
            minFreqLink = self.freqMap[self.minFreq]
 
            # 链表头部节点是最少访问次数中,最远访问的文件,我们需要删除它
            removeNode = minFreqLink.head
            # 删除对应文件后,文件系统容量新增
            self.capacity += removeNode.val
 
            # 执行删除操作,freqMap和keyMap都要删除掉对应文件的记录
            minFreqLink.remove(removeNode)
            self.keyMap.pop(removeNode.key)
 
            # 如果删除后,最少访问次数的链表空了,则需要找到下一个最少访问次数的链表
            if minFreqLink.size == 0:
                # 最少次数的链表空了,则删除对应最少次数的记录
                del self.freqMap[self.minFreq]
 
                # 更新最少次数
                if len(self.freqMap.keys()) > 0:
                    self.minFreq = min(self.freqMap.keys())
                else:
                    # 文件系统没有缓存文件了,则最少次数为0,表示文件系统空了
                    self.minFreq = 0
 
        # 新增文件,则文件系统容量减少
        self.capacity -= val
        # 新增文件的访问次数为1,因此最少访问次数变为了1
        self.minFreq = 1
        node = Node(key, val, self.minFreq)
        # 执行新增操作,freqMap和keyMap都要新增对应文件的记录
        self.freqMap.setdefault(self.minFreq, Link())
        self.freqMap.get(self.minFreq).addLast(node)
        self.keyMap[key] = node
 
    def incNodeFreq(self, node):
        """
        增加key的访问次数
        :param node: key对应的node
        """
        # 由于key的访问次数增加,因此要从原访问次数的链表中删除
        self.freqMap[node.freq].remove(node)
 
        # 如果原链表删除当前key对应的节点后为空,且原链表对应的访问次数就是最少访问次数
        if self.freqMap[node.freq].size == 0:
            # 最少次数的链表空了,则删除对应最少次数的记录
            del self.freqMap[node.freq]
 
            # 则最少访问次数对应的key没有了,因此最少访问次数++(即当前key访问次数++后,当前key的访问次数还是最少访问次数)
            if node.freq == self.minFreq:
                self.minFreq += 1
 
        # 当前key访问次数++
        node.freq += 1
 
        # 将当前key对应的node转移到对应增加后的访问次数对应的链表尾部(最近访问)
        self.freqMap.setdefault(node.freq, Link())
        self.freqMap[node.freq].addLast(node)
 
 
# 输入获取
m = int(input())
 
lfu = LFUCache(m)
 
n = int(input())
 
for _ in range(n):
    operation = input().split()
 
    op = operation[0]
    fileName = operation[1]
 
    if "put" == op:
        fileSize = int(operation[2])
        lfu.put(fileName, fileSize)
    else:
        lfu.get(fileName)
 
if lfu.capacity == m:
    print("NONE")
else:
    ans = list(lfu.keyMap.keys())
    ans.sort()
    print(",".join(ans))

员工派遣

#include <iostream>

using namespace std;
typedef long long LL;

LL x, y, cntx, cnty;

bool check(LL k, LL x, LL y, LL cntx, LL cnty) {
    LL a = k / x - k / (x * y);
    LL b = k / y - k / (x * y);
    LL c = k / (x * y);
    LL d = k - a - b - c;
    return d >= max(0LL, cntx - b) + max(0LL, cnty - a);
}

int main()
{
    cin >> x >> y >> cntx >> cnty;

    LL l = 1, r = 1e18;
    while (l < r) 
    {
        LL mid = l + r >> 1;
        if (check(mid, x, y, cntx, cnty)) r = mid;
        else l = mid + 1;
    }
    cout << l << endl;
    return 0;
}

跳格子3

#include <stdio.h>
#include <math.h>
 
#define MAX_SIZE 100000
 
int main() {
    // 输入获取
    int n;
    scanf("%d", &n);
 
    int scores[n];
    for (int i = 0; i < n; i++) {
        scanf("%d", &scores[i]);
    }
 
    int k;
    scanf("%d", &k);
 
    // 核心代码
    // 第i个格子,可以从第i-k个格子~第i-1个格子调过来,因此本题滑窗的长度相当于k+1
    k++;
 
    // dp[i]表示跳到第i个格子能得到的最大分数
    int dp[n];
    dp[0] = scores[0];
 
    // 单调队列(单调递减,队首是滑窗最大值)
    int queue[MAX_SIZE];
    int queue_size = 0;
 
    queue[queue_size++] = scores[0];
    int queue_first_idx = 0;
 
    // 初始滑窗的形成过程(即只有新增尾部元素的过程)
    for (int i = 1; i < fmin(k, n); i++) { // 注意当k > n时, 需要取n, 此时只有滑窗形成过程,没有滑窗移动过程
        // dp[i] = max(dp[0]~dp[i-1]) + scores[i]
        // 即单调队列队首保存的是max(dp[0]~dp[i-1])
        dp[i] = queue[queue_first_idx] + scores[i];
 
        // 保持单调队列的单调递减性,即如果后入队的dp[i] 大于 队尾元素,则队尾元素出队
        while (queue_size > 0 && dp[i] > queue[queue_first_idx + queue_size - 1]) {
            queue_size--;
        }
 
        // 当队尾没有比dp[i]更小的元素后,dp[i]才能入队
        queue[queue_first_idx + queue_size] = dp[i];
        queue_size++;
    }
 
    // 滑窗的右移过程(即相较于老滑窗失去一个首元素,新增一个尾元素)
    for (int i = k; i < n; i++) {
        // 如果滑窗失去的元素dp[i - k],和单调队列的队首元素queue[0]相同,则单调队列需要弹出头部元素
        if (dp[i - k] == queue[queue_first_idx]) {
            queue_first_idx++;
            queue_size--;
        }
 
        // 下面逻辑同之前
        dp[i] = queue[queue_first_idx] + scores[i];
 
        while (queue_size > 0 && dp[i] > queue[queue_first_idx + queue_size - 1]) {
            queue_size--;
        }
 
        queue[queue_first_idx + queue_size] = dp[i];
        queue_size++;
    }
 
    printf("%d\n", dp[n - 1]);
 
    return 0;
}

贪吃的猴子

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>

int main() {
    int n;
    std::cin >> n;

    std::vector<int> nums(n);

    for (int i = 0; i < n; i++) {
        std::cin >> nums[i];
    }

    int k;
    std::cin >> k;

    int number = 0;
    for (int i = 0; i < k; i++) {
        number += nums[i];
    }

    int ans = number;
    int l = k - 1, r = n - 1;

    while (l >= 0) {
        number -= nums[l];
        number += nums[r];
        ans = std::max(ans, number);
        r--;
        l--;
    }

    std::cout << ans << std::endl;

    return 0;
}

项目排期

#include<iostream>
#include<algorithm>
#include<vector>
#include <numeric>
using namespace std;

// 定义检查函数,判断在x天内是否能完成n个人的m个工作
bool check(int x, int cnt, vector<int>& choose, vector<int>& w) {
    if (cnt == w.size()) {
        return true;
    }
    for (int i = 0; i < choose.size(); i++) {
        // 避免重复选择同一个人
        if (i > 0 && choose[i] == choose[i - 1]) {
            continue;
        }
        // 如果第i个人能够完成当前工作,则更新状态并继续检查下一个工作
        if (choose[i] + w[cnt] <= x) {
            choose[i] += w[cnt];
            if (check(x, cnt + 1, choose, w)) {
                return true;
            }
            choose[i] -= w[cnt];
        }
    }
    return false;
}


vector<int> w;
int num;

int main() 
{
    while (cin >> num)   w.push_back(num);
    int n = w.back();
    w.pop_back();

    // 对工作时间向量进行降序排序
    sort(w.begin(), w.end(), greater<int>{});

    // 初始化二分查找的左右边界
    int l = 1, r = accumulate(w.begin(), w.end(), 0);

    // 使用二分查找确定最少需要的天数
    while (l < r) 
    {
        int mid = l + r >> 1;

        // 初始化选择数组,用于标记每个人完成的工作时间
        vector<int> choose(n, 0);

        if (check(mid, 0, choose, w)) r = mid;
        else l = mid + 1;   
    }
    cout << l << endl;

    return 0;
}

亲子游戏

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

// 定义广度优先搜索函数
int bfs(queue<pair<int, int>>& q, vector<vector<int>>& g, vector<vector<int>>& w, vector<int>& dx, vector<int>& dy, int n) {
    while (!q.empty()) {
        // 从队列中取出当前位置
        pair<int, int> t = q.front();
        q.pop();
        int x = t.first, y = t.second;

        // 如果当前位置为终点,返回糖果数量
        if (g[x][y] == -2) {
            return w[x][y];
        }

        // 遍历四个方向
        for (int i = 0; i < 4; i++) {
            int x1 = x + dx[i], y1 = y + dy[i];

            // 判断是否越界或者是不可访问的位置
            if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n || g[x1][y1] == -1) {
                continue;
            }

            // 如果该位置未访问过,将其加入队列,并初始化糖果数量为0
            if (w[x1][y1] == 0) {
                q.push({x1, y1});
                w[x1][y1] = 0;
            }

            // 更新糖果数量,取当前位置糖果数和上一步位置的糖果数量之和的最大值
            w[x1][y1] = max(w[x1][y1], max(0, g[x1][y1]) + w[x][y]);
        }
    }
    // 如果无法到达终点,返回-1
    return -1;
}

int main() {
    int n;
    cin >> n;

    // 存储糖果数量的二维数组w,初始值为0
    vector<vector<int>> w(n, vector<int>(n, 0));

    // 存储起点坐标的队列
    queue<pair<int, int>> q;

    // 存储地图元素的二维数组g
    vector<vector<int>> g(n, vector<int>(n, 0));

    // 读取地图元素并初始化起点和糖果数量数组
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> g[i][j];
            if (g[i][j] == -3) {  // 添加起点
                q.push({i, j});
                w[i][j] = 0;
            }
        }
    }

    // 四个方向的移动
    vector<int> dx = {-1, 1, 0, 0};
    vector<int> dy = {0, 0, 1, -1};

    // 调用广度优先搜索函数获取结果
    int result = bfs(q, g, w, dx, dy, n);
    cout << result << endl;

    return 0;
}

可以处理的最大任务数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector<int> a[100005];

int solve() {
    int ans = 0;
    priority_queue<int, vector<int>, greater<int>> pq; // 使用小顶堆作为待处理队列

    for (int i = 0; i < 100005; i++) {
        while (!pq.empty() && pq.top() < i) {
            pq.pop(); // 第一步:移除已经结束的任务
        }

        if (!a[i].empty()) {
            for (int j = 0; j < a[i].size(); j++) {
                pq.push(a[i][j]); // 第二步:将当前时刻开始的任务加入队列
            }
        }

        if (!pq.empty()) {
            ans++;
            pq.pop(); // 第三步:从队列中取出结束时间最早的任务,安排在这一天
        }
    }

    return ans;
}

int main() {
    int n;
    cin >> n; // 输入任务数量

    for (int i = 0; i < n; i++) {
        int x, y;
        cin >> x >> y;
        a[x].push_back(y); // 存储任务的开始和结束时间
    }

    cout << solve() << endl;

    return 0;
}

推荐多样性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
#define MAX_ROWS 100
#define MAX_ROW_LEN 10000
 
/* 链表节点 */
typedef struct Node {
    int val;
    struct Node *next;
} Node;
 
/* 链表 */
typedef struct Link {
    int size;
    Node *head;
    Node *tail;
} Link;
 
// 创建链表
Link *new_Link() {
    Link *link = (Link *) malloc(sizeof(Link));
 
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
 
    return link;
}
 
// 尾插
void addLast_Link(Link *link, int val) {
    Node *node = (Node *) malloc(sizeof(Node));
    node->val = val;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
// 头删
int removeFirst_Link(Link *link) {
    if (link->size == 0) exit(-1);
 
    Node *removed = link->head;
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    int val = removed->val;
    free(removed);
 
    return val;
}
 
int main() {
    int n, k;
    scanf("%d %d", &n, &k);
 
    getchar();
 
    Link *lists[MAX_ROWS];
    int lists_size = 0;
 
    char s[MAX_ROW_LEN];
    while (gets(s)) {
        // 本地测试,以空行作为输入截止条件
        if (strlen(s) == 0) break;
 
        Link *link = new_Link();
 
        char *token = strtok(s, " ");
        while (token != NULL) {
            addLast_Link(link, atoi(token));
            token = strtok(NULL, " ");
        }
 
        lists[lists_size++] = link;
    }
 
    // 窗口矩阵,k行n列,每一列对应一个窗口,这里将二维矩阵一维化,方便后面赋值
    int windows[k * n];
    // 窗口矩阵中正在赋值的索引位置
    int idx = 0;
    // 正在从第level个列表中取值
    int level = 0;
 
    // 当窗口矩阵填满后,结束循环
    while (idx < k * n) {
        // 当前轮次是否发生了"借"动作
        int flag = 0;
 
        // 从第level个列表中取前n个元素
        for (int i = 0; i < n; i++) {
            windows[idx++] = removeFirst_Link(lists[level]);
 
            // 如果第level个列表没有元素了,则继续切到下一个列表中"借"
            if (lists[level]->size == 0 && lists_size > 1) {
                // 删除第level个空列表
                for (int j = level + 1; j < lists_size; j++) {
                    lists[j - 1] = lists[j];
                }
                lists_size--;
                level %= lists_size; // 防止越界
                flag = 1;   // 发生了"借"动作
            }
        }
 
        // 如果没有发生"借"动作,则需要切到下一行
        if (!flag) {
            level = (level + 1) % lists_size; // 防止越界
        }
    }
 
    // 遍历列号
    for (int j = 0; j < n; j++) {
        // 遍历行号
        for (int i = 0; i < k; i++) {
            // 按列打印
            printf("%d", windows[i * n + j]);
            if (j != n - 1 || i != k - 1) {
                printf(" ");
            }
        }
    }
 
    return 0;
}

两个字符串间的最短路径问题

#include <stdio.h>
#include <string.h>
#include <math.h>
 
int main() {
    char A[10000];
    scanf("%s", A);
 
    char B[10000];
    scanf("%s", B);
 
    int m = (int) strlen(B);
    int n = (int) strlen(A);
 
    // 初始时preRow记录第一行上各点到(0,0)点的最短距离,即为(0,0) -> (0,j) 的直线路径
    int preRow[n + 1];
    for (int j = 0; j <= n; j++) {
        preRow[j] = j;
    }
 
    // 初始时curRow记录第二行上各点到(0,0)点的最短距离
    int curRow[n + 1];
 
    for (int i = 1; i <= m; i++) {
        // curRow[0]是指 (i, 0)点 到 (0,0)点 的最短距离,即为(0,0) -> (i, 0) 的直线路径
        curRow[0] = i;
 
        for (int j = 1; j <= n; j++) {
            if (A[j - 1] == B[i - 1]) {
                // 如果可以走斜线,则选走斜线的点
                curRow[j] = preRow[j - 1] + 1;
            } else {
                // 如果不能走斜线,则从当前点的上方点、左方点中选择一个较小值
                curRow[j] = (int) fmin(preRow[j], curRow[j - 1]) + 1;
            }
        }
 
        // 压缩
        for (int j = 0; j <= n; j++) preRow[j] = curRow[j];
    }
 
    printf("%d", curRow[n]);
 
    return 0;
}

跳马

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;
const int N = 30;
char g[N][N];               // 存储地图
int n, m;                   // 地图的行数和列数
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};   // 马的移动方向(x轴)
int dy[8] = {-2, 2, -2, 2, -1, 1, -1, 1};   // 马的移动方向(y轴)
unordered_map<int, vector<vector<int>>> dist;   // 标记从每一个马的当前位置出发到达(i, j)的最短距离

// BFS算法,计算从马的当前位置出发到达目标位置(i, j)的最短距离
void bfs(int x, int y, int u, int k) {
    queue<pair<int, int>> q;
    q.push({x, y});
    dist[u][x][y] = 0;

    while (q.size()) {
        auto [x1, y1] = q.front();
        q.pop();

        for (int i = 0; i < 8; i++) {
            int x2 = x1 + dx[i], y2 = y1 + dy[i];

            // 判断是否越界,以及是否已经访问过,距离是否超过了k
            if (x2 < 0 || x2 >= n || y2 < 0 || y2 >= m || dist[u][x2][y2] <= dist[u][x1][y1] + 1 || dist[u][x1][y1] >= k) {
                continue;
            }

            dist[u][x2][y2] = dist[u][x1][y1] + 1;
            q.push({x2, y2});
        }
    }
}

int main() {
    cin >> n >> m;   // 输入地图的行数和列数
    vector<pair<int, int>> pos;   // 存储马的初始位置

    // 遍历输入地图
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int u = i * m + j;
            dist[u] = vector<vector<int>>(n, vector<int>(m, 0x3f3f3f3f));  // 初始化距离为无穷大
            cin >> g[i][j];

            // 如果当前位置是马的起点,则进行BFS计算最短距离,并将起点位置加入pos列表
            if (g[i][j] >= '1' && g[i][j] <= '9') {
                bfs(i, j, u, g[i][j] - '0');
                pos.push_back({i, j});
            }
        }
    }

    int ans = 0x3f3f3f3f;   // 初始化最终答案为无穷大

    // 遍历所有可能的目标位置
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int cnt = 0;

            // 遍历所有马的起点位置,计算到达目标位置的总距离
            for (auto &p : pos) {
                int u = p.first * m + p.second;

                // 如果有某个马无法到达目标位置,则将cnt设为无穷大
                if (dist[u][i][j] == 0x3f3f3f3f) {
                    cnt = 0x3f3f3f3f;
                    break;
                }

                cnt += dist[u][i][j];
            }

            // 更新最终答案为所有目标位置中的最小值
            ans = min(ans, cnt);
        }
    }

    // 输出最终答案,如果无法到达任何目标位置,则输出-1
    if (ans == 0x3f3f3f3f) puts("-1");
    else cout << ans << endl;

    return 0;
}

路口最短时间问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <limits.h>
 
#define MAX_SIZE 10
 
int n, m;
int lights[MAX_SIZE][MAX_SIZE];
int timePerRoad;
int rowStart, colStart;
int rowEnd, colEnd;
 
int offsets[4][2] = {{-1, 0},
                     {1,  0},
                     {0,  -1},
                     {0,  1}};
 
int visited[MAX_SIZE][MAX_SIZE] = {0};
 
/*!
 * 根据三点坐标,确定拐弯方向
 * @param preX 前一个点横坐标
 * @param preY 前一个点纵坐标
 * @param curX 当前点横坐标
 * @param curY 当前点纵坐标
 * @param nextX 下一个点横坐标
 * @param nextY 下一个点纵坐标
 * @return cur到next的拐弯方向, >0 表示向左拐, ==0 表示直行(含调头), <0 表示向右拐
 */
int getDirection(int preX, int preY, int curX, int curY, int nextX, int nextY) {
    // 向量 pre->cur
    int dx1 = curX - preX;
    int dy1 = curY - preY;
 
    // 向量 cur->next
    int dx2 = nextX - curX;
    int dy2 = nextY - curY;
 
    // 两个向量的叉积 >0 表示向左拐, ==0 表示直行(含调头), <0 表示向右拐
    return dx1 * dy2 - dx2 * dy1;
}
 
/*!
 * 暴力搜索
 * @param curX 当前位置横坐标
 * @param curY 当前位置纵坐标
 * @param preX 上一个位置横坐标
 * @param preY 上一个位置纵坐标
 * @param cost 到达当前位置花费的时间
 * @param minCost 记录起点到终点的最小花费时间
 */
void dfs(int curX, int curY, int preX, int preY, int cost, int minCost[]) {
    // 如果到达当前前花费的时间cost 达到了 已知minCost,那么后续路径就没必要探索了,因为必然要比minCost大
    if (cost >= minCost[0]) {
        return;
    }
 
    // 如果当前点是终点,且花费的时间cost更少,则更新minCost
    if (curX == rowEnd && curY == colEnd) {
        minCost[0] = cost;
        return;
    }
 
    // 否则,从当前位置的四个方向继续探索路径
    for (int i = 0; i < 4; i++) {
        // 新位置
        int nextX = curX + offsets[i][0];
        int nextY = curY + offsets[i][1];
 
        // 新位置越界或者已经访问过,则不能访问,继续其他方向探索
        if (nextX < 0 || nextX >= n || nextY < 0 || nextY >= m || visited[nextX][nextY]) {
            continue;
        }
 
        // 标记新位置访问过
        visited[nextX][nextY] = 1;
 
        // 根据pre,cur,next三点,判断拐弯方向
        int direction = getDirection(preX, preY, curX, curY, nextX, nextY);
 
        // cur到达next位置必须要增加timePreRoad个时间
        int increment = timePerRoad;
        // preX=-1, preY=-1 表示pre位置不存在,此时探索下一个位置不需要花费等待周期
        if (preX >= 0 && preY >= 0 && direction >= 0) {
            // pre位置存在,且cur->next是左拐或者直行,则需要增加当前位置对应的等待周期时间
            increment += lights[curX][curY];
        }
 
        // 递归进入新位置
        dfs(nextX, nextY, curX, curY, cost + increment, minCost);
 
        // 回溯
        visited[nextX][nextY] = 0;
    }
}
 
int getResult() {
    // 记录访问过的点,防止走回路
    // 初始时起点位置标记为访问过
    visited[rowStart][colStart] = 1;
 
    // 记录起点到终点的最小花费时间,这里minCost定义为数组,是为了其在dfs函数调用结束后,不会被释放内存,因为它是引用类型变量
    int minCost[] = {INT_MAX};
    // 开始暴搜所有起点到终点的路径
    dfs(rowStart, colStart, -1, -1, 0, minCost);
    return minCost[0];
}
 
int main() {
    scanf("%d %d", &n, &m);
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &lights[i][j]);
        }
    }
 
    scanf("%d", &timePerRoad);
 
    scanf("%d %d", &rowStart, &colStart);
 
    scanf("%d %d", &rowEnd, &colEnd);
 
    printf("%d\n", getResult());
 
    return 0;
}

字符串拼接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 31
 
char s[MAX_SIZE];
int s_len;
int n;
 
/*!
 * 全排列求解
 * @param pre 排列最后一个字符在cArr中的位置
 * @param level 排列的长度
 * @param used used[i] 用于标记 s[i] 元素是否已使用
 * @param count 符号要求的排列有几个
 * @return count
 */
int dfs(int pre, int level, int used[], int count) {
    // 当排列长度到达n,则是一个符合要求的排列
    if (level == n) {
        // 符合要求的排列个数+1
        return ++count;
    }
 
    for (int i = 0; i < s_len; i++) {
        // 每个字符只能用一次
        if (used[i]) continue;
 
        // 相同的字符不能相邻, pre指向前面一个被选择的字符的在s中的位置,i指向当前被选择的字符在s中的位置
        if (pre >= 0 && s[i] == s[pre]) continue;
 
        // 树层去重(去除重复排列)
        if (i > 0 && s[i] == s[i - 1] && !used[i - 1]) continue;
 
        used[i] = 1;
        count = dfs(i, level + 1, used, count);
        used[i] = 0;
    }
 
    return count;
}
 
int cmp(const void *a, const void *b) {
    return *((char *) a) - *((char *) b);
}
 
int getResult() {
    int i = 0;
    while (s[i] != '\0') {
        // 输入非法
        if (s[i] < 'a' || s[i] > 'z') return 0;
        i++;
    }
 
    s_len = i;
 
    if (s_len < n) {
        // 无法拼接出满足条件的字符串
        return 0;
    }
 
    // 排序s,可以方便后面求解全排列时,进行树层去重
    qsort(s, i, sizeof(char), cmp);
 
    int used[MAX_SIZE] = {0};
    return dfs(-1, 0, used, 0);
}
 
int main() {
    scanf("%s", s);
    scanf("%d", &n);
 
    printf("%d\n", getResult());
 
    return 0;
}

Wonderland

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<int> cost, days;
    int x;

    // 读取输入,将输入的数据存入days数组
    while (cin >> x) {
        days.push_back(x);
    }

    // 初始化cost数组,将days数组的前四个元素放入cost数组中
    for (int i = 0; i < 4; i++) {
        cost.push_back(days[0]);
        days.erase(days.begin());
    }

    int choose[] = {1, 3, 7, 30};  // 不同的购买方案
    bool isPlay[366] = {false};

    // 标记游玩日期
    for (int x : days) {
        isPlay[x] = true;
    }

    int f[366];

    // 将f数组初始化为正无穷
    fill(f, f + 366, 1e9);
    f[0] = 0; // 初始条件

    for (int i = 1; i < 366; i++) {
        if (isPlay[i]) {  // 当天是游玩日
            for (int j = 0; j < 4; j++) {  // 考虑四种不同的购买方案
                f[i] = min(f[i], f[max(0, i - choose[j])] + cost[j]);
            }
        } else {
            f[i] = f[i - 1]; // 当天不是游玩日,花费与前一天相同
        }
    }

    // 输出最终结果
    cout << f[365] << endl;

    return 0;
}

伐木工

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;

    vector<int> f(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        f[i] = i;
        for (int j = 1; j < i; j++) {
            f[i] = max(f[i], max(f[i - j] * j, (i - j) * j));
        }
    }

    vector<int> res;
    int m = n;
    while (m >= 1) {
        if (f[m] == m) {
            res.push_back(m);
            break;
        }
        for (int k = m - 1; k > 1; k--) {
            if (k * (m - k) == f[m]) {
                res.push_back(k);
                res.push_back(m - k);
                m = 0;
                break;
            } else if (k * f[m - k] == f[m]) {
                res.push_back(k);
                m -= k;
                break;
            }
        }
    }

    sort(res.begin(), res.end());
    for (int i : res) {
        cout << i << " ";
    }

    return 0;
}

抢7游戏(dp)

#include <stdio.h>
 
int main() {
    int m;
    scanf("%d", &m);
 
    // dpA[i] 表示 A 叫 数字i 的方案数
    long long dpA[m + 2];
    // 初始化dpA[i]
    for (int i = 0; i < m + 2; i++) dpA[i] = 0;
    // 由于是A从m开始叫,因此A叫m的方案数为1
    dpA[m] = 1;
 
    // dpB[i] 表示 B叫 数字i 的方案数
    long long dpB[m + 2];
    // 初始化dpB[i]
    for (int i = 0; i < m + 2; i++) dpB[i] = 0;
 
    for (int i = m - 1; i >= 7; i--) {
        // B叫数字i的方案数 = A叫数字i+1的方案数 + A叫数字i+2的方案数
        dpB[i] = dpA[i + 1] + dpA[i + 2];
        // A叫数字i的方案数 = B叫数字i+1的方案数 + B叫数字i+2的方案数
        dpA[i] = dpB[i + 1] + dpB[i + 2];
    }
 
    // 返回B叫7的方案数
    printf("%lld", dpB[7]);
 
    return 0;
}

寻找最优的路测线路

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
 
#define MAX_SIZE 400
 
int cmp(const void *a, const void *b) {
    return *((int *) b) - *((int *) a);
}
 
int main() {
    int r, c;
    scanf("%d %d", &r, &c);
 
    int matrix[r][c];
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
 
    // dist[i]记录的 起点0 到 终点i 的所有路径中“最大的”最小权值节点的权值
    // 其中 i 是将二维坐标一维化后的值,比如(x,y)坐标一维化后为 x * c + y; (c是列数)
    // dist[i] 记录的 “最大的”最小权值节点的权值,因此需要初始化为一个 "最小的" 最小权值节点的权值,方便后面被更大者取代,由于本题节点的最小权值>=0,因此这里可以初始化为0
    int dist[MAX_SIZE] = {0};
    // 起点0 到 终点0 路径的最小权值节点就是自身,即matrix[0][0]点的权重
    dist[0] = matrix[0][0];
 
    // 优先队列记录路径(终点),并且路径中的最小权值节点的权值越大,优先级越高
    int pq[MAX_SIZE] = {0};
    int pq_size = 0;
 
    // 初始时将(0,0)入队
    pq[pq_size++] = 0;
 
    // 上下左右的方向偏移量
    int offsets[4][2] = {{-1, 0},
                         {1,  0},
                         {0,  -1},
                         {0,  1}};
 
    while (pq_size > 0) {
        // 取出优先队列中优先级最大的路径(终点)
        int u = pq[--pq_size];
 
        // 将一维化坐标u,解析为二维坐标(x,y)
        int x = u / c;
        int y = u % c;
 
        // 已找到dist[r-1][c-1]最优解,则可以提前结束
        if (x == r - 1 && y == c - 1) break;
 
        // 向上下左右四个方向探索
        for (int i = 0; i < 4; i++) {
            // 新位置坐标
            int newX = x + offsets[i][0];
            int newY = y + offsets[i][1];
 
            // 新位置越界则无法访问
            if (newX < 0 || newX >= r || newY < 0 || newY >= c) continue;
 
            // 新位置的一维化坐标
            int v = newX * c + newY;
            // 当前路径(终点u)的最小权值节点的权值为dist[u]
            // 要加入当前路径的新位置的点的权值 matrix[newX][newY]
            // 那么形成的新路径的最小权值节点的权值即为 w = min(dist[u], matrix[newX][newY])
            int w = (int) fmin(dist[u], matrix[newX][newY]);
 
            // 形成的新路径的终点为 v(即新位置一维化坐标)
            // 而dist[v]记录的是起点到点v的所有路径中“最大的”最小权值节点
            if (dist[v] < w) {
                // 因此如果dist[v] < w的话,则更新dist[v]
                dist[v] = w;
                // 并将新路径加入优先队列,参与下一轮比较
                pq[pq_size++] = v;
                // 优先级排序,由于43行是pq尾删,即尾部优先级最大,因此这里升序
                qsort(pq, pq_size, sizeof(int), cmp);
            }
        }
    }
 
    // 返回起点(0,0)到终点(r-1, c-1)的所有路径中"最大的"最小权值节点的权值
    printf("%d\n", dist[r * c - 1]);
 
    return 0;
}

篮球游戏

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 200
 
typedef struct ListNode {
    int ele;
    struct ListNode *prev;
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, int ele) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->ele = ele;
    node->prev = NULL;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        node->prev = link->tail;
        link->tail = node;
    }
 
    link->size++;
}
 
int removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
        link->head->prev = NULL;
    }
 
    link->size--;
 
    int res = removed->ele;
 
    free(removed);
 
    return res;
}
 
int removeLast_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->tail;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->tail = link->tail->prev;
        link->tail->next = NULL;
    }
 
    link->size--;
 
    int res = removed->ele;
 
    free(removed);
 
    return res;
}
 
int main() {
    int inputs[MAX_SIZE];
    int inputs_size = 0;
 
    while (scanf("%d", &inputs[inputs_size++])) {
        if (getchar() != ',') break;
    }
 
    int outputs[MAX_SIZE];
    int outputs_size = 0;
 
    while (scanf("%d", &outputs[outputs_size++])) {
        if (getchar() != ',') break;
    }
 
    // 利用队列结构模拟圆桶
    LinkedList *queue = new_LinkedList();
    // outputs[index]是要被取出的篮球的编号
    int index = 0;
 
    // 记录题解
    char res[MAX_SIZE] = {'\0'};
    int res_size = 0;
 
    for (int i = 0; i < inputs_size; i++) {
        // 按照放入顺序,从圆桶右边放入
        addLast_LinkedList(queue, inputs[i]);
 
        // 然后开始尝试取出
        while (queue->size > 0) {
            // 圆桶左边的篮球的编号
            int left = queue->head->ele;
            // 圆桶右边的篮球的编号
            int right = queue->tail->ele;
 
            if (left == outputs[index]) {
                // 优先比较圆桶左边的篮球是不是当前要取出的篮球,优先左边的原因是:当桶只有一个篮球的情况下,必须从左边取出
                res[res_size++] = 'L';
                removeFirst_LinkedList(queue);
                index++;
            } else if (right == outputs[index]) {
                // 比较圆桶右边的篮球是不是当前要取出的篮球
                res[res_size++] = 'R';
                removeLast_LinkedList(queue);
                index++;
            } else {
                // 如果圆桶左右两边都不是要取出的球,则本轮取出流程结束
                break;
            }
        }
    }
 
    // 最终如果圆桶空了,则说明所有球都取出了,否则按照给定要求无法取出所有球
    if (queue->size != 0) {
        puts("NO");
    } else {
        puts(res);
    }
 
    return 0;
}

矩阵匹配

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
using namespace std;

int n, m, K; // 声明变量 n, m, K,分别表示行数、列数和第K大元素的数量
vector<vector<int>> myMap; // 声明二维向量 myMap,用于存储输入的数字

// findMuniu 函数:实现匈牙利匹配算法,用于在矩阵中找到一个增广路径
bool findMuniu(int x, vector<vector<bool>>& mp, vector<bool>& chw, vector<int>& match) {
    for (int j = 1; j <= m; j++) {
        if (mp[x][j] && chw[j]) {
            chw[j] = false;
            if (match[j] == 0 || findMuniu(match[j], mp, chw, match)) {
                match[j] = x;
                return true;
            }
        }
    }
    return false;
}

// check 函数:检查给定的数字 p 是否可以添加到匹配图中
bool check(int p) {
    vector<vector<bool>> mp(n + 1, vector<bool>(m + 1, false)); // 声明二维向量 mp,用于存储匹配图

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            mp[i][j] = (myMap[i][j] <= p); // 构建匹配图
        }
    }

    int ans = 0;
    vector<int> match(m + 1, 0); // 声明一维向量 match,用于存储匹配的数字

    for (int i = 1; i <= n; i++) {
        vector<bool> chw(m + 1, true); // 声明一维向量 chw,表示当前可用的数字
        if (findMuniu(i, mp, chw, match)) {
            ans++;
        }
    }

    return ans >= n - K + 1; // 返回匹配数是否大于等于 n - K + 1
}

// solve 函数:使用二分查找算法找到矩阵中可以选出 M!/N! 种组合数组中第 K 大的数字的最小值
int solve(int mx) {
    int l = 1, r = mx;
    int ans = 0;

    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            ans = mid;
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }

    return ans;
}

// 主函数
int main() {
    cin >> n >> m >> K; // 输入 n, m, K 的值
    myMap.resize(n + 1, vector<int>(m + 1, 0)); // 调整 myMap 的大小

    int mx = 0;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> myMap[i][j]; // 输入矩阵中的数字
            mx = max(mx, myMap[i][j]); // 计算矩阵中的最大值
        }
    }

    int result = solve(mx); // 调用 solve 函数
    cout << result << endl; // 输出结果

    return 0;
}

最小矩阵宽度

#include <stdio.h>
#include <limits.h>
#include <math.h>
 
#define MAX_SIZE 1000
 
// 矩阵行数, 矩阵列数
int n, m;
// 矩阵
int matrix[MAX_SIZE][MAX_SIZE];
 
// 目标数组长度
int k;
// cnts[num] 记录的是 目标数组中num元素的个数
int cnts[MAX_SIZE] = {0};
 
int getResult() {
    // 未完成匹配的元素的个数
    int total = k;
 
    // 记录最小子矩阵的宽度
    int minLen = INT_MAX;
 
    // 当前子矩阵的左边界(列号)
    int l = 0;
    // 当前子矩阵的右边界(列号)
    int r = 0;
 
    // 如果右边界未越界,则可以继续尝试找最小子矩阵
    while (r < m) {
        // 将第r列所有元素纳入子矩阵
        for (int i = 0; i < n; i++) {
            // 第r列的元素num
            int num = matrix[i][r];
 
            // cnts[num] 记录的是 目标数组中num元素的个数,也可以理解为:目标数组中num元素剩余未匹配的个数
            // 如果num不是目标数组元素,则cnts[num]初始时必然为0,对于非目标数组元素num, 即使进行了 cnts[num]--, 也不影响总的未匹配数量 total
            // 如果num是目标数组元素,则cnts[num]初始时必然大于0,且随着子矩阵扩大范围,如果子矩阵中包含num元素个数超过了初始cnts[num]数量,则超出部分起不到匹配效果,即不能影响总的未匹配数量
            if (cnts[num]-- > 0) {
                total--;
            }
        }
 
        // 纳入r列后,看看总的未匹配元素数量total还有几个,如果total为0,则说明当前子矩阵匹配到了所有目标数组元素
        while (total == 0) {
            // 若此时子矩阵宽度 r - l + 1 更小,则更新最小子矩阵宽度
            minLen = (int) fmin(minLen, r - l + 1);
 
            // 由于当前子矩阵已经匹配到所有目标数组元素,因此下一步应该将 l 右移,尝试更小宽度的子矩阵
            for (int i = 0; i < n; i++) {
                // l 右移,相当于当前子矩阵移除了第 l 列所有元素,被移除的元素num如果是目标数组元素,则对应的未匹配数量应该被恢复
                int num = matrix[i][l];
 
                // 如果当前num不是目标数组元素,或者当前num是目标数组元素,但是属于超出部分(这两种情况必然cnts[num] < 0),
                //    则对应num元素的恢复,不能影响到整体未匹配数量total,
                // 如果当前num是目标数组元素,且不是超出部分(此时必然cnts[num] >= 0),则对应num元素的恢复,会影响到整体未匹配数量total
                if (cnts[num]++ >= 0) {
                    total++;
                }
            }
 
            // l右移,且下一轮要继续检查l右移后的子矩阵是否依旧能覆盖目标数组所有元素
            l++;
        }
 
        // r右移
        r++;
    }
 
    if (minLen == INT_MAX) {
        return -1;
    } else {
        return minLen;
    }
}
 
int main() {
    scanf("%d %d", &n, &m);
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
 
    scanf("%d", &k);
 
    for (int i = 0; i < k; i++) {
        int num;
        scanf("%d", &num);
        cnts[num]++;
    }
 
    printf("%d\n", getResult());
 
    return 0;
}

启动多任务排序

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;

// 用邻接表存储图
vector<int> g[26];
// 存储每个节点的入度
int d[26];
// 记录节点是否被访问过
bool vis[26];

int main() {
    string s;

    // 读取输入,构建图的邻接表
    while (cin >> s) {
        int a = s[0] - 'A', b = s[3] - 'A';
        d[a]++;
        g[b].push_back(a);
        vis[a] = vis[b] = true;
    }

    // 使用队列进行拓扑排序
    queue<int> q;
    // 存储拓扑排序的结果
    vector<int> res, v;

    // 初始化队列,将入度为0且存在的节点加入队列和结果集合中
    for (int i = 0; i < 26; i++) {
        if (!d[i] && vis[i]) {
            q.push(i);
            v.push_back(i);
        }
    }

    // 开始拓扑排序
    while (q.size()) {
        int sz = q.size();
        // 将当前层次的节点按字典序排序
        sort(v.begin(), v.end());
        // 将排序后的节点加入结果集合
        for (int &x : v) {
            res.push_back(x);
        }
        v.clear();

        // 处理当前层次的节点
        while (sz--) {
            int t = q.front();
            q.pop();

            // 遍历当前节点的邻接表
            for (int &x : g[t]) {
                d[x]--;
                // 如果某个相邻节点入度为0,加入队列和结果集合中
                if (!d[x]) {
                    q.push(x);
                    v.push_back(x);
                }
            }
        }
    }

    // 输出拓扑排序的结果
    for (int &x : res) {
        char ch = x + 'A';
        cout << ch << " ";
    }

    return 0;
}

贪心歌手

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
 
int cmp(const void *a, const void *b) {
    return *((int *) b) - *((int *) a);
}
 
int main() {
    int t, n;
    scanf("%d %d", &t, &n);
 
    // roadCost是A~B城市必需的路程时间
    int roadCost = 0;
    for (int i = 0; i < n + 1; i++) {
        int cost;
        scanf("%d", &cost);
        roadCost += cost;
    }
 
    // remain是刨去必要的路程时间后,剩余可以用于赚钱的时间
    int remain = t - roadCost;
 
    // 如果没有剩余时间可以用,则赚不到钱
    if (remain <= 0) {
        puts("0");
        return 0;
    }
 
    // 优先队列(降序数组)记录赚到的钱, 即数组尾巴是某天赚的最少的钱
    int pq[remain + 1];
    int pq_size = 0;
 
    for (int i = 0; i < n; i++) {
        // 第一天卖唱可以赚m,后续每天的收入会减少d
        int m, d;
        scanf("%d %d", &m, &d);
 
        // 只要在当前城市还有钱赚,那么就继续待
        while (m > 0) {
            // 只有remain天可以赚钱,超出的时间不能赚钱,因此需要比较超出的时间赚的钱m,和前面时间中赚的最少的钱pq.peek
            if (pq_size >= remain) {
                // pq.peek只可能是某座城市停留的最后一天的赚的钱,因为每座城市都是停留的最后一天赚的钱最少
                if (m > pq[pq_size - 1]) {
                    // 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq.peek多,那么就赚pq.peek钱的那天时间节约下来,给当天用
                    pq_size--;
                } else {
                    // 如果当前城市当天赚的钱m,比前面天里面赚的最少的pq.peek还少,则当前城市继续待下去赚的钱只会更少,因此没必要呆下去了
                    break;
                }
            }
 
            // 如果所有城市停留时间没有超出remain天,或者当天是超出的时间,但是比前面赚的最少的一天的赚的更多,则赚m更优
            pq[pq_size++] = m;
            qsort(pq, pq_size, sizeof(int), cmp);
 
            //  每天收入减少d
            m -= d;
        }
    }
 
    int ans = 0;
    for (int i = 0; i < pq_size; i++) {
        ans += pq[i];
    }
 
    printf("%d\n", ans);
 
    return 0;
}

反射计数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int m, n, y, x, sy, sx, t;
    cin >> m >> n >> y >> x >> sy >> sx >> t;

    vector<string> g(n);
    for (int i = 0; i < n; i++) {
        cin >> g[i];
    }

    int ans = 0;
    while (t >= 0) {
        if (g[x][y] == '1') {
            ans += 1;
        }
        int x1 = x + sx;
        int y1 = y + sy;
        if (x1 < 0 || x1 >= n) {
            sx = -sx;
        }
        if (y1 < 0 || y1 >= m) {
            sy = -sy;
        }
        x += sx;
        y += sy;
        t -= 1;
    }
    cout << ans << endl;
    return 0;
}

模拟目录管理功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
/** 树节点 **/
typedef struct TreeNode {
    char curDicName[11]; // 当前目录名
    struct TreeNode *father; // 父目录(只能有一个)
    struct LinkedList *children; // 子目录(可以有多个,这里使用链表记录)
} TreeNode;
 
/** 链表节点 **/
typedef struct ListNode {
    TreeNode *ele; // 链表用于记录多个子目录,因此链表节点的内容就是树节点
    struct ListNode *next;
} ListNode;
 
/** 链表 **/
typedef struct LinkedList {
    ListNode *head;
    ListNode *tail;
    int size;
} LinkedList;
 
/** 树 **/
typedef struct Tree {
    TreeNode *root; // 记录树根节点
    TreeNode *cur; // 记录当前目录对应的节点
} Tree;
 
/**  链表结构方法  **/
// 初始化链表
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
 
    link->head = NULL;
    link->tail = NULL;
    link->size = 0;
 
    return link;
}
 
// 尾插链表
void addLast_LinkedList(LinkedList *link, TreeNode *ele) {
    ListNode *listNode = (ListNode *) malloc(sizeof(ListNode));
    listNode->ele = ele;
    listNode->next = NULL;
 
    if(link->size == 0) {
        link->head = listNode;
        link->tail = listNode;
    } else {
        link->tail->next = listNode;
        link->tail = listNode;
    }
 
    link->size++;
}
 
// 遍历链表,获取指定节点的内容
TreeNode *get_LinkedList(LinkedList *link, char *dicName) {
    ListNode *curListNode = link->head;
    while (curListNode != NULL) {
        if (strcmp(curListNode->ele->curDicName, dicName) == 0) {
            return curListNode->ele;
        }
        curListNode = curListNode->next;
    }
    return NULL;
}
 
/**  树形结构方法  **/
TreeNode *new_TreeNode(char *curDicName, TreeNode *father) {
    TreeNode *treeNode = (TreeNode *) calloc(1, sizeof(TreeNode));
 
    strcpy(treeNode->curDicName, curDicName);
    treeNode->father = father;
    treeNode->children = new_LinkedList();
 
    return treeNode;
}
 
// 初始化树
Tree *new_Tree() {
    Tree *tree = (Tree *) malloc(sizeof(Tree));
 
    // 由于目录名结尾都要带'/',因此可以认为根目录是空串,后期拼接时再尾部追加'/'
    // 另外根目录没有父目录,因此父目录设置为NULL
    tree->root = new_TreeNode("", NULL);
    // 初始时,当前目录就是根目录
    tree->cur = tree->root;
 
    return tree;
}
 
// 创建指定目录
void mkdir_Tree(Tree *tree, char *dicName) {
    TreeNode *p = get_LinkedList(tree->cur->children, dicName);
 
    // mkdir 目录名称,如 mkdir abc 为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作
    if (p != NULL) {
        return;
    }
 
    TreeNode *treeNode = new_TreeNode(dicName, tree->cur);
    addLast_LinkedList(tree->cur->children, treeNode);
}
 
// 跳转到指定目录
void cd_Tree(Tree *tree, char *dicName) {
    if (strcmp(dicName, "..") == 0) {
        // cd .. 为返回上级目录,如果目录不存在则不执行任何操作
        if (tree->cur->father != NULL) {
            // cur 变更指向上级目录
            tree->cur = tree->cur->father;
        }
    } else {
        TreeNode *p = get_LinkedList(tree->cur->children, dicName);
 
        // cd 目录名称,如 cd abc 为进入abc目录,如果目录不存在则不执行任何操作
        if (p != NULL) {
            // cur 变更指向下级目录
            tree->cur = p;
        }
    }
}
 
// 输出当前路径字符串
char *pwd_Tree(Tree *tree) {
    char *tmp = (char *) calloc(10000, sizeof(char));
    char *res = (char *) calloc(10000, sizeof(char));
 
    // 倒序路径,即不停向上找父目录
    TreeNode *cur = tree->cur;
    while (cur != NULL) {
        strcpy(tmp, res);
 
        strcpy(res, cur->curDicName);
        strcat(res, "/");
        strcat(res, tmp);
        cur = cur->father;
    }
 
    return res;
}
 
int main() {
    // 初始化目录结构
    Tree *tree = new_Tree();
 
    // 记录最后一条命令的输出
    char lastCommandOutPut[10000];
 
    char s[50];
    while (gets(s)) {
        // 本地测试解开此行注释
         if(strlen(s) == 0) break;
 
        char *cmd_key = strtok(s, " ");
        char *cmd_val = strtok(NULL, " ");
 
        if (strcmp(cmd_key, "pwd") == 0) {
            // pwd 命令不需要参数
            if (cmd_val != NULL) {
                continue;
            }
            strcpy(lastCommandOutPut, pwd_Tree(tree));
        } else if (strcmp(cmd_key, "mkdir") == 0 || strcmp(cmd_key, "cd") == 0) {
            // 约束:mkdir 和 cd 命令的参数仅支持单个目录,如:mkdir abc 和 cd abc
            if (cmd_val == NULL) continue;
 
            char *p = strtok(NULL, " ");
            if (p != NULL) continue;
 
            if(!(strcmp(cmd_key, "cd") == 0 && strcmp(cmd_val, "..") == 0)) {
                unsigned long long len = strlen(cmd_val);
 
                // 目录名约束校验
                // 约束:目录名称仅支持小写字母
                // 约束:不支持嵌套路径和绝对路径,如 mkdir abc/efg,cd abc/efg,mkdir /abc/efg,cd /abc/efg 是不支持的。
                // 关于嵌套路径和绝对路径,我简单理解就是cmd_val含有'/'字符,可以被小写字母判断涵盖住
                int i = 0;
                for (; i < len; i++) {
                    char c = cmd_val[i];
 
                    if (c < 'a' || c > 'z') {
                        break;
                    }
                }
 
                if(i != len) {
                    continue;
                }
            }
 
            if(strcmp(cmd_key, "mkdir") == 0) {
                mkdir_Tree(tree, cmd_val);
                // 题目进要求输出最后一个命令的运行结果,因此,对于无输出的命令,我认为需要覆盖掉前面的命令的输出结果
                memset(lastCommandOutPut, '\0', strlen(lastCommandOutPut));
            } else {
                cd_Tree(tree, cmd_val);
                // 题目进要求输出最后一个命令的运行结果,因此,对于无输出的命令,我认为需要覆盖掉前面的命令的输出结果
                memset(lastCommandOutPut, '\0', strlen(lastCommandOutPut));
            }
        }
    }
 
    puts(lastCommandOutPut);
 
    return 0;
}

特殊的加密算法

#include <stdio.h>
 
#define MAX_SIZE 201
 
// 明文数字个数
int n;
// 明文
int datas[MAX_SIZE];
 
// 密码本矩阵大小
int m;
// 密码本
int secrets[MAX_SIZE][MAX_SIZE];
 
// 记录密码本中元素值等于“明文第一个数字”的所有元素的位置
int starts[MAX_SIZE] = {0};
int starts_size = 0;
 
// 上,左,右,下偏移量,注意这里的顺序是有影响的,即下一步偏移后产生的密文的字符序必然是:上 < 左 < 右 < 下
int offsets[4][2] = {{-1, 0},
                     {0,  -1},
                     {0,  1},
                     {1,  0}};
 
/*!
 *
 * @param x 当前位置横坐标
 * @param y 当前位置纵坐标
 * @param index datas[index]是将要匹配的明文数字
 * @return 是否找到符合要求的路径
 */
int dfs(int x, int y, int index, int path[], int *path_size, int used[][MAX_SIZE]) {
    // 已找到明文最后一个数字,则找到符合要求的路径
    if (index == n) {
        return 1;
    }
 
    // 否则,进行上、左、右、下四个方向偏移,注意这里的顺序是有影响的,即下一步偏移后产生的密文的字符序必然是:上 < 左 < 右 < 下
    for (int i = 0; i < 4; i++) {
        // 新位置
        int newX = x + offsets[i][0];
        int newY = y + offsets[i][1];
 
        // 新位置越界,或者新位置已使用,或者新位置不是目标值,则跳过
        if (newX < 0 || newX >= m || newY < 0 || newY >= m || used[newX][newY] ||
            secrets[newX][newY] != datas[index]) {
            continue;
        }
 
        // 递归进入新位置
        path[(*path_size)++] = newX * m + newY;
        used[newX][newY] = 1;
 
        // 如果当前分支可以找到符合要求的路径,则返回
        if (dfs(newX, newY, index + 1, path, path_size, used)) {
            return 1;
        }
 
        // 否则,回溯
        used[newX][newY] = 0;
        (*path_size)--;
    }
 
    return 0;
}
 
void getResult() {
    for (int i = 0; i < starts_size; i++) {
        // 出发位置
        int x = starts[i] / m;
        int y = starts[i] % m;
 
        // used[i][j]用于记录密码本(i,j)元素是否已使用
        int used[MAX_SIZE][MAX_SIZE] = {0};
        // 出发点位置元素已使用
        used[x][y] = 1;
 
 
        // 记录结果路径各节点位置
        int path[MAX_SIZE] = {0};
        int path_size = 0;
        // 出发点位置记录
        path[path_size++] = starts[i];
 
        // 开始深搜
        if (dfs(x, y, 1, path, &path_size, used)) {
            // 找到符合要求的路径,则打印
            for (int j = 0; j < path_size; j++) {
                int pos = path[j];
                printf("%d %d", pos / m, pos % m);
 
                if (j < path_size - 1) {
                    printf(" ");
                }
            }
 
            return;
        }
    }
 
    // 找不到符合要求的路径,则打印error
    puts("error");
}
 
int main() {
    scanf("%d", &n);
 
    for (int i = 0; i < n; i++) {
        scanf("%d", &datas[i]);
    }
 
 
    scanf("%d", &m);
 
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &secrets[i][j]);
 
            // 如果密码本(i,j)位置元素指等于明文第一个数字值,则记录(i,j)作为一个出发位置
            if (secrets[i][j] == datas[0]) {
                starts[starts_size++] = i * m + j;
            }
        }
    }
 
    getResult();
 
    return 0;
}

田忌赛马

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
 
#define MAX_SIZE 10
 
int a[MAX_SIZE];
int a_size = 0;
 
int b[MAX_SIZE];
int b_size = 0;
 
int maxBiggerCount = 0;
int ans = 0;
 
void dfs(int level, int used[], int biggerCount) {
    if (level >= a_size) {
        if (biggerCount > maxBiggerCount) {
            maxBiggerCount = biggerCount;
            ans = 1;
        } else if (biggerCount == maxBiggerCount) {
            ans += 1;
        }
 
        return;
    }
 
    for (int i = 0; i < a_size; i++) {
        if (used[i]) continue;
 
        used[i] = 1;
        // biggerCount记录当前全排列中a[level] > b[level]的位置的数量, 此时a[level] == a[i]
        dfs(level + 1, used, biggerCount + (a[i] > b[level] ? 1 : 0));
        used[i] = 0;
    }
}
 
int main() {
    while (scanf("%d", &a[a_size++])) {
        if (getchar() != ' ') break;
    }
 
    while (scanf("%d", &b[b_size++])) {
        if (getchar() != ' ') break;
    }
 
    int used[MAX_SIZE] = {0};
 
    // 求解a的全排列
    dfs(0, used, 0);
 
    printf("%d\n", ans);
 
    return 0;
}

最长子字符串的长度(二)(5OJ)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
 
#define MAX_SIZE 500000
 
char s[MAX_SIZE];
 
typedef struct ListNode {
    int ele;
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, int ele) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->ele = ele;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
int removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    int res = removed->ele;
 
    free(removed);
 
    return res;
}
 
int getResult() {
    int status = 0b000;
 
    // map[i] 用于记录 状态i 出现的过的所有位置
    LinkedList *map[8];
    for (int i = 0; i < 8; i++) {
        map[i] = new_LinkedList();
    }
 
    addLast_LinkedList(map[0], -1);
 
    int maxLen = 0;
 
    int n = (int) strlen(s);
 
    for (int i = 0; i < n * 2; i++) {
        // 第二轮时,i>=s.length(),此时i需要对s.length()求余,避免后面越界
        char c = s[i % n];
 
        if (c == 'l') {
            status ^= 0b100;
        } else if (c == 'o') {
            status ^= 0b010;
        } else if (c == 'x') {
            status ^= 0b001;
        }
 
        if (i < n) {
            // 第一轮时,i ∈ [0, s.length()), 左闭右开
            // 记录该状态出现过的所有位置
            addLast_LinkedList(map[status], i);
        }
 
        while (map[status]->size > 0) {
            // status状态最早出现的位置
            int earliest = map[status]->head->ele;
 
            // i 是当前位置,和 earliest 位置的状态相同
            if (i - earliest > n) {
                // 如果 [earliest, i] 范围子串长度超过s串长度,则说明earliest左越界,应该尝试更大一点的earliest
                removeFirst_LinkedList(map[status]);
            } else {
                // 如果 [earliest, i] 范围子串长度未超过s串长度,则该范围子串就是一个符合要求的子串,记录此时子串长度
                maxLen = (int) fmax(maxLen, i - earliest);
                break;
            }
        }
    }
 
    return maxLen;
}
 
int main() {
    gets(s);
 
    printf("%d\n", getResult());
 
    return 0;
}

考古学家(py)

# 输入获取
n = int(input())
arr = input().split()
 
 
# 全局变量
path = []
used = [False] * n
cache = set()
 
 
# 全排列求解
def dfs():
    if len(path) == n:
        cache.add("".join(path))
        return
 
    for i in range(n):
        if used[i]:
            continue
 
        # 树层去重
        if i > 0 and arr[i] == arr[i-1] and not used[i-1]:
            continue
 
        path.append(arr[i])
        used[i] = True
        dfs()
        used[i] = False
        path.pop()
 
 
# 算法入口
def getResult():
    # 排序是为了让相同元素相邻,方便后面树层去重
    arr.sort()
    dfs()
 
    # 输出石碑文字的组合(按照升序排列)
    for v in sorted(list(cache)):
        print(v)
 
 
# 算法调用
getResult()

最大社交距离

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <bits/stdc++.h>
#define MAX_N 10000
using namespace std;
int N,res;
bool rec[505];
int cur;
int main(){
    scanf("%d",&N);
    while(getchar() != '[');
    getchar();getchar();
    rec[0] = 1;
    while (scanf("%d",&cur) == 1){
        // printf("cur:%d\n",cur);
        if(cur < 0){
            cur = -cur;
            rec[cur] = 0;
        }else if(cur == 1){
            int prv = 0;
            int ct = 0;
            int curmax = -1;
            for(int i = 1; i < N; i++){
                if(rec[i]){
                    if(curmax < (ct-1)/2 && ct >= 1){
                        curmax = (ct-1)/2;
                        res = (prv+i)/2;
                    }
                    prv = i;
                    ct = 0;
                }else ct++;
            }
            if(curmax == -1 && ct == 0){
                res = -1;
                break;
            }
            if(ct != 0){
                if(ct-1 > curmax){
                    res = N-1;
                }
            }
            rec[res] = 1;

            // //test res
            // printf("res:%d\n",res);
        }
        getchar();

        // //test rec[]
        // for(int i = 0; i < N; i++) printf("%d ",rec[i]);
        // putchar('\n');
    }
    // //test rec[]
    // for(int i = 0; i < N; i++) printf("%d ",rec[i]);
    // putchar('\n');

    printf("%d\n",res);
    return 0;
}

文本统计分析(py)

# 算法入口
import re
 
 
def fn(s):
    s = re.sub("\\[\"']", "", s)  # 替换\"和\'为空串
    s = re.sub("\".*?\"", "a", s)  # 将成对双引号及其中内容替换为空串
    s = re.sub("'.*?'", "a", s)  # 将成对单引号及其中内容替换为空串
    s = re.sub("-.+", "", s)  # 将-往后的注释替换为空串
    s = re.sub("\\s+", "", s)  # 将空白字符替换为空串
    s = re.sub(";+", ";", s)  # 将连续分号替换为单个分号
    return s
 
 
def getResult(lines):
    s = "".join(map(fn, lines))
 
    # 题目描述说:文本以”;”分隔,最后一条可以没有”;”
    # 为了避免复杂处理,这里无论最后一条文本有没有分号,都加一个
    s += ";"
 
    # 下面处理主要是为了处理跨行文本
    """
    比如
    aaaa;
    ;aaaa
    比如
    ;aaaa
    ;aaaa
    """
    s = re.sub(";+", ";", s)
    s = re.sub("^;", "", s)
 
    # 记录文本条数
    count = 0
 
    for c in s:
        if c == ';':
            count += 1  # 此时一行有几个分号,就代表几条文本
 
    return count
 
 
# 输入获取
lines = []
 
while True:
    line = input()
 
    if line != "":
        lines.append(line)
    else:
        print(getResult(lines))
        break

信道分配

#include <stdio.h>
 
#define MAX_SIZE 20
 
int getResult(int R, int N[], int D);
int binary_sub(int minuend[], int subtrahend[], int size);
int calc_bin(const int bin[], int bin_size);
 
int main() {
    int R;
    scanf("%d", &R);
 
    int N[MAX_SIZE] = {0};
    for(int i=0; i<=R; i++) {
        scanf("%d", &N[i]);
    }
 
    int D;
    scanf("%d", &D);
 
    printf("%d\n", getResult(R, N, D));
 
    return 0;
}
 
int getResult(int R, int N[], int D) {
    int subtrahend[50];
    int subtrahend_size = 0;
 
    // 将D值转化为二进制形式,并且为了和N[]的阶位进行对应,这里将D的二进制进行了反转
    while(D > 0) {
        subtrahend[subtrahend_size++] = D % 2;
        D /= 2;
    }
 
    // count记录N能承载几个D
    int count = 0;
 
    // N中高阶信道的单个信道就能满足D,因此这些高阶信道有几个,即能承载几个D
    for(int i = R; i >= subtrahend_size; i--) {
        // R ~ subtrahend.length 阶的单个信道就能承载一个D,因此这些信道有几个,就能承载几个D
        count += N[i];
    }
 
    // 0 ~ subtrahend.length - 1 阶的单个信道无法承载一个D,因此这些阶需要组合起来才能承载一个D
    int minuend[subtrahend_size];
    for(int i=0; i<subtrahend_size; i++) {
        minuend[i] = N[i];
    }
 
    // 进行二进制减法
    while(binary_sub(minuend, subtrahend, subtrahend_size)) {
        count++;
    }
 
    return count;
}
 
/*!
 *
 * @param minuend 被减数
 * @param subtrahend 减数
 * @param size 被减数和件数的二进制位数
 * @return 减法运算后,被减数是否为正数
 */
int binary_sub(int minuend[], int subtrahend[], int size) {
    // 进行减法运算逻辑, 从高位开始
    for(int i=size - 1; i >= 0; i--) {
        if(minuend[i] >= subtrahend[i]) {
            // 如果对应位的信道数足够,则直接相减
            minuend[i] -= subtrahend[i];
        } else {
            // 如果对应位的信道数不足,此时有两种策略,一是向低位借,一是向高位借
            // 具体向哪里借,需要看 minuend 的 [0,i] 低位部分是否能够承载 subtrahend[0, i] 低位部分
            if(calc_bin(minuend, i+1) < calc_bin(subtrahend, i+1)) {
                // 如果minuend 的 [0,i]不能承载,则向高位借,即从j=i+1位开始借
                int j = i + 1;
                while (j < size) {
                    if(minuend[j] > 0) {
                        // 如果高位 j 有信道可借,则借
                        minuend[j] -= 1;
                        return 1;
                    } else {
                        // 否则继续向更高位探索
                        j += 1;
                    }
                }
                // 如果所有高位都没有富余信道数,则说明减法结果为负数
                return 0;
            } else {
                // 如果minuend 的 [0,i]可以承载,则向低位借(向低位借,可以避免浪费)
                // 此时minuend[i]为负数,表示欠债
                minuend[i] -= subtrahend[i];
                // 将当前阶位的欠债,转移到前面的低阶位上,注意转移时,欠债x2
                minuend[i-1] += minuend[i] << 1;
                // 转移后,当前阶位的欠债变为0
                minuend[i] = 0;
            }
        }
    }
 
    return 1;
}
 
int calc_bin(const int bin[], int bin_size) {
    int ans = 0;
    for(int i=0; i<bin_size; i++) {
        ans += bin[i] * (1 << i);
    }
    return ans;
}

欢乐的周末

#include <stdio.h>
#include <stdlib.h>
 
/** 并查集定义 **/
typedef struct {
    int *fa;
    int count;
} UFS;
 
UFS *new_UFS(int n) {
    UFS *ufs = (UFS *) malloc(sizeof(UFS));
 
    ufs->fa = (int *) malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++) {
        ufs->fa[i] = i;
    }
 
    ufs->count = n;
 
    return ufs;
}
 
int find_UFS(UFS *ufs, int x) {
    if (x != ufs->fa[x]) {
        ufs->fa[x] = find_UFS(ufs, ufs->fa[x]);
        return ufs->fa[x];
    }
    return x;
}
 
void union_UFS(UFS *ufs, int x, int y) {
    int x_fa = find_UFS(ufs, x);
    int y_fa = find_UFS(ufs, y);
 
    if (x_fa != y_fa) {
        ufs->fa[y_fa] = x_fa;
        ufs->count--;
    }
}
 
int main() {
    // 长度m表示行数, 宽度n表示列数
    int m, n;
    scanf("%d %d", &m, &n);
 
    int matrix[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
 
    UFS *ufs = new_UFS(n * m);
 
    // 记录小华,小为的位置
    int huawei[2];
    int huawei_size = 0;
 
    // 记录餐厅的位置
    int restaurants[m * n];
    int restaurants_size = 0;
 
    // 上下左右四个方向偏移量
    int offsets[4][2] = {{-1, 0},
                         {1,  0},
                         {0,  -1},
                         {0,  1}};
 
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if(matrix[i][j] == 1) continue;
 
            // 二维坐标(i, j) 转为 一维坐标pos
            int pos = i * n + j;
 
            switch (matrix[i][j]) {
                case 2:
                    // 收集小华,小为的位置
                    huawei[huawei_size++] = pos;
                    break;
                case 3:
                    // 收集餐厅的位置
                    restaurants[restaurants_size++] = pos;
                    break;
            }
 
            for (int k = 0; k < 4; k++) {
                int newI = i + offsets[k][0];
                int newJ = j + offsets[k][1];
                if (newI >= 0 && newI < m && newJ >= 0 && newJ < n && matrix[newI][newJ] != 1) {
                    // 如果(i,j)和(newI,newJ)位置都是非1,则合并
                    union_UFS(ufs, pos, newI * n + newJ);
                }
            }
        }
    }
 
    // 小华所在连通分量的根
    int hua_fa = find_UFS(ufs, huawei[0]);
    // 小为所在连通分量的根
    int wei_fa = find_UFS(ufs, huawei[1]);
 
    if (hua_fa != wei_fa) {
        // 如果小华和小为的不属于同一个连通分量,则二人无法去往相同餐厅
        puts("0");
    } else {
        // 找出和小华、小为在同一个连通分量里面的餐厅
        int ans = 0;
        for (int i = 0; i < restaurants_size; i++) {
            if (find_UFS(ufs, restaurants[i]) == hua_fa) {
                ans++;
            }
        }
        printf("%d\n", ans);
    }
 
    return 0;
}

二叉树的广度优先遍历

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
/** 链表定义 **/
typedef struct ListNode {
    char post[27];
    char mid[27];
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, char *post, char *mid) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    strcpy(node->post, post);
    strcpy(node->mid, mid);
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
ListNode *removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    return removed;
}
 
// res记录题解
char res[27];
int res_size = 0;
 
/*!
 * 字符串截取(左闭右开)
 * @param s 字符串
 * @param start 起始位置(包含)
 * @param end 结束位置(不包含)
 * @return 指定区间的子串
 */
char *subString(char *s, int start, int end) {
    int len = end - start;
 
    char *tmp = (char *) calloc(len + 1, sizeof(char));
    strncat(tmp, s + start, len);
 
    return tmp;
}
 
/*!
 * 本方法用于从后序遍历、中序遍历序列中分离出:根,以及其左、右子树的后序、中序遍历序列
 * @param post 后序遍历结果
 * @param mid 中序遍历结果
 * @param queue BFS的执行队列
 */
void devideLR(char *post, char *mid, LinkedList *queue) {
    // 后序遍历的最后一个元素就是根
    char rootEle = post[strlen(post) - 1];
    // 将根加入题解
    res[res_size++] = rootEle;
 
    // 在中序遍历中找到根的位置rootIdx,那么该位置左边就是左子树,右边就是右子树
    int rootIdx = strchr(mid, rootEle) - mid;
 
    // 左子树长度,左子树是中序遍历的0~rootIdx-1范围,长度为rootIdx
    // 如果存在左子树,即左子树长度大于0
    if (rootIdx > 0) {
        // 则从后序遍历中,截取出左子树的后序遍历
        char* leftPost = subString(post, 0, rootIdx);
        // 从中序遍历中,截取出左子树的中序遍历
        char* leftMid = subString(mid, 0, rootIdx);
        // 将左子树的后、中遍历序列加入执行队列
        addLast_LinkedList(queue, leftPost, leftMid);
    }
 
    // 如果存在右子树,即右子树长度大于0
    if (strlen(post) - 1 - rootIdx > 0) {
        // 则从后序遍历中,截取出右子树的后序遍历
        char* rightPost = subString(post, rootIdx, strlen(post) - 1);
        // 从中序遍历中,截取出右子树的中序遍历
        char* rightMid = subString(mid, rootIdx + 1, strlen(mid));
        // 将右子树的后、中遍历序列加入执行队列
        addLast_LinkedList(queue, rightPost, rightMid);
    }
}
 
int main() {
    char post[27];
    char mid[27];
 
    scanf("%s %s", post, mid);
 
    // 广度优先搜索的执行队列,先加入左子树,再加入右子树
    LinkedList *queue = new_LinkedList();
 
    // 层序遍历出来的元素存放在res中
    devideLR(post, mid, queue);
 
    while (queue->size > 0) {
        ListNode* node = removeFirst_LinkedList(queue);
        devideLR(node->post, node->mid, queue);
    }
 
    puts(res);
 
    return 0;
}
 
 
 

图像物体的边界

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;

const int N = 5010;

int a[N][N];  // 存储地图信息,表示地图中每个位置是否可以到达
int n, m;  // 地图的行数和列数

int dx[8] = {0, 0, -1, 1, -1, 1, -1, 1};  // 用于遍历相邻位置的行偏移
int dy[8] = {-1, 1, 0, 0, -1, 1, 1, -1};  // 用于遍历相邻位置的列偏移

int visited[N][N];  // 记录每个位置是否已经被访问过

// 深度优先搜索,用于遍历地图中的连通块
void dfs(int x, int y) {
    // 边界条件判断
    if (x < 1 || x > n || y < 1 || y > m) return;
    if (a[x][y] == 0) return;  // 如果当前位置不可到达,返回
    if (visited[x][y]) return;  // 如果当前位置已经被访问过,返回
    visited[x][y] = 1;  // 标记当前位置为已访问

    // 遍历当前位置的所有相邻位置
    for (int i = 0; i < 8; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        dfs(nx, ny);  // 递归调用DFS
    }
}

int mp[N][N];  // 存储输入的地图信息

int main() {
    // 读取地图的行数和列数
    cin >> n >> m;

    // 读取地图信息
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> mp[i][j];
        }
    }

    // 根据地图信息更新a数组,表示可到达的位置
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (mp[i][j] == 5) {
                // 如果当前位置为5,则更新其周围相邻位置可到达
                for (int k = 0; k < 8; k++) {
                    int ni = i + dx[k];
                    int nj = j + dy[k];
                    if (mp[ni][nj] == 1) {
                        a[ni][nj] = 1;
                    }
                }
            }
        }
    }

    int cnt = 0;  // 记录连通块的数量

    // 遍历地图中的每个位置
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // 如果当前位置可到达且未被访问过,进行DFS遍历
            if (a[i][j] == 1 && visited[i][j] == 0) {
                cnt++;  // 连通块数量加1
                dfs(i, j);  // 对连通块进行DFS遍历
            }
        }
    }

    // 输出连通块的数量
    cout << cnt << endl;

    return 0;
}


找单词(5oj)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
char g[N][N];
int n;
string s;
bool vis[N][N];
int dx[4]={-1,1,0,0}, dy[4]={0,0,1,-1};

bool dfs(int cnt, int x, int y, vector<pair<int,int>>& path) {
    // 判断是否越界、已访问或者当前位置字符不匹配
    if (x < 0 || x >= n || y < 0 || y >= n || vis[x][y] || g[x][y] != s[cnt]) {
        return false;
    }

    // 如果已经找到字符串的最后一个字符,输出路径并返回 true
    if (cnt == s.size() - 1) {
        int m = path.size();
        for (int i = 0; i < m; i++) {
            printf("%d,%d", path[i].first, path[i].second);
            if (i < m - 1) {
                printf(",");
            }
        }
        return true;
    }

    // 标记当前位置已访问
    vis[x][y] = true;

    // 遍历四个方向
    for (int i = 0; i < 4; i++) {
        int a = dx[i] + x;
        int b = dy[i] + y;

        // 记录路径
        path.push_back({a, b});

        // 递归调用 dfs
        if (dfs(cnt + 1, a, b, path)) {
            return true;
        }

        // 回溯,移除路径
        path.pop_back();
    }

    // 恢复当前位置未访问状态
    vis[x][y] = false;
    return false;
}

int main() {
    scanf("%d\n", &n);

    // 读取迷宫字符数组 g
    for (int i = 0; i < n; i++) {
        string t;
        cin >> t;
        for (int j = 0; j < n; j++) {
            g[i][j] = t[j * 2];
        }
    }

    // 读取目标字符串 s
    cin >> s;

    // 在迷宫中寻找字符串 s 的路径
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (g[i][j] == s[0]) {
                memset(vis, 0, sizeof vis);
                vector<pair<int, int>> path = {{i, j}};
                if (dfs(0, i, j, path)) {
                    break;
                }
            }
        }
    }

    return 0;
}

找城市\

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include<bits/stdc++.h>
using namespace std;

const int N = 1010;
vector<int> g[N];
int n, num;
vector<int> res;
bool vis[N];

// 深度优先搜索,计算以 u 为根的子树节点数量
int dfs(int u, int fa) {
    int cnt = 1;
    vis[u] = true;
    for (int& x : g[u]) {
        if (x == fa || vis[x]) continue;
        cnt += dfs(x, u);
    }
    return cnt;
}

// 枚举切除每个节点后的最大子树,更新最小的最大子树数量及对应节点
void solve(int u) {
    memset(vis, 0, sizeof vis);
    vis[u] = true;  // 当前节点被切割
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i]) continue;
        cnt = max(cnt, dfs(i, 0));
    }
    if (cnt < num) {
        res.clear();
    }
    if (cnt <= num) {
        num = cnt;
        res.push_back(u);
    }
}

int main() {
    cin >> n;
    for (int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    num = 1e9;
    for (int i = 1; i <= n; i++) {  // 枚举切除第 i 个节点的最大子树
        solve(i);
    }
    for (int& x : res) cout << x << " ";
    return 0;
}

可以组成网络的服务器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <iostream>
#include <vector>
using namespace std;

int n, m;
vector<vector<int>> g;
vector<vector<bool>> st;
vector<int> dx = {-1, 1, 0, 0};
vector<int> dy = {0, 0, 1, -1};
int cnt, res;

void dfs(int i, int j) {
    // 计数器加1
    cnt++;
    // 将当前位置的标记为true
    st[i][j] = true;
    // 遍历四个方向
    for (int d = 0; d < 4; d++) {
        // 计算新的位置
        int x = dx[d] + i, y = dy[d] + j;
        // 检查新位置是否在网格内且未访问过
        if (x >= 0 && x < n && y >= 0 && y < m && !st[x][y] && g[x][y] == 1) {
            // 如果满足条件,则递归访问新位置
            dfs(x, y);
        }
    }
}

int main() {
    // 读取网格的行数和列数
    cin >> n >> m;
    // 创建网格和标记矩阵
    g.resize(n, vector<int>(m));
    st.resize(n, vector<bool>(m));

    // 读取网格的内容
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> g[i][j];
        }
    }

    // 遍历网格,找到所有的单元格(除了边界以外的单元格),并对其进行深度优先遍历(DFS)
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (g[i][j] == 1 && !st[i][j]) {
                // 计算当前单元格的访问次数
                cnt = 0;
                // 对当前单元格进行深度优先遍历(DFS)
                dfs(i, j);
                // 更新最大访问次数
                res = max(res, cnt);
            }
        }
    }

    // 输出结果
    cout << res << endl;

    return 0;
}

快递员的烦恼

#include <stdio.h>
#include <limits.h>
 
#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
#define MAX_SIZE 11
#define MAX_ID 1000
 
int n;
int dist[MAX_SIZE][MAX_SIZE];
int path[MAX_SIZE][MAX_SIZE];
 
int ans;
 
 
/**
   * 找一条经过所有点的最短路径,我们可以求解所有点形成的全排列,每一个全排列都对应一条经过所有点的路径,只是经过点的先后顺序不同 //
   * 求某个全排列过程中,可以通过dist数组,累计上一个点i到下一个点j的最短路径dist[i][j]
   *
   * @param pre 上一个点, 初始为0,表示从披萨店出发
   * @param sum 当前全排列路径累计的路径权重
   * @param used 全排列used数组,用于标记哪些点已使用过
   * @param level 用于记录排列的长度
   */
void dfs(int pre, int sum, int used[], int level) {
    if (level == n) {
        // 此时pre是最后一个客户所在点,送完最后一个客户后,司机需要回到披萨店,因此最终累计路径权重为 sum + dist[pre][0]
        // 我们保留最小权重路径
        ans = MIN(ans, sum + dist[pre][0]);
        return;
    }
 
    for (int i = 1; i <= n; i++) {
        if (used[i]) continue;
 
        used[i] = 1;
        dfs(i, sum + dist[pre][i], used, level + 1);
        used[i] = 0;
    }
}
 
// floyd算法求解图中任意两点之间的最短路径
void floyd() {
    for (int k = 0; k < n + 1; k++) {
        for (int i = 0; i < n + 1; i++) {
            for (int j = 0; j < n + 1; j++) {
                // newDist是经过k后,i->j的距离
                int newDist = dist[i][k] + dist[k][j];
                // 如果newDist是i->j的更短路径
                if (newDist < dist[i][j]) {
                    // 则更新i->j的最短距离
                    dist[i][j] = newDist;
                    // 且此更短距离需要经过k, path[i][j]即记录 i->j 最短距离下需要经过点 k
                    path[i][j] = k;
                }
            }
        }
    }
}
 
int main() {
    int m;
    scanf("%d %d", &n, &m);
 
    for (int i = 0; i < n + 1; i++) {
        for (int j = 0; j < n + 1; j++) {
            // 初始时默认i,j不相连,即i,j之间距离无穷大
            if (i != j) {
                dist[i][j] = INT_MAX;
            }
            path[i][j] = -1;
        }
    }
 
    // 由于本题的客户id不是顺序的,因此这里需要将客户id离散化处理
    int map[MAX_ID];
 
    for (int i = 1; i <= n; i++) {
        int id, dis;
        scanf("%d %d", &id, &dis);
 
        // 离散化处理
        map[id] = i;
 
        // 投递站到客户之间的距离distance
        dist[0][i] = dis;
        dist[i][0] = dis;
    }
 
    for (int i = 1; i <= m; i++) {
        int id1, id2, dis;
        scanf("%d %d %d", &id1, &id2, &dis);
 
        int i1 = map[id1];
        int i2 = map[id2];
 
        // 客户与客户之间的距离信息
        dist[i1][i2] = dis;
        dist[i2][i1] = dis;
    }
 
    // floyd算法调用
    floyd();
 
    // ans记录经过所有点后回到出发点的最短距离
    ans = INT_MAX;
 
    // 全排列模拟经过所有点的路径
    int used[MAX_SIZE] = {0};
    dfs(0, 0, used, 0);
 
    printf("%d\n", ans);
}

查找一个有向网络的头节点和尾节点

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_SIZE 10000
 
/** 基于链表实现队列 **/
typedef struct ListNode {
    int ele;
    struct ListNode *next;
} ListNode;
 
typedef struct LinkedList {
    int size;
    ListNode *head;
    ListNode *tail;
} LinkedList;
 
LinkedList *new_LinkedList() {
    LinkedList *link = (LinkedList *) malloc(sizeof(LinkedList));
    link->size = 0;
    link->head = NULL;
    link->tail = NULL;
    return link;
}
 
void addLast_LinkedList(LinkedList *link, int ele) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->ele = ele;
    node->next = NULL;
 
    if (link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }
 
    link->size++;
}
 
int removeFirst_LinkedList(LinkedList *link) {
    if (link->size == 0) exit(-1);
 
    ListNode *removed = link->head;
 
    if (link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }
 
    link->size--;
 
    return removed->ele;
}
 
int cmp(const void *a, const void *b) {
    return *((int *) a) - *((int *) b);
}
 
int main() {
    int n;
    scanf("%d", &n);
 
    // 记录每个点的入度
    int inDegree[MAX_SIZE] = {0};
    // 记录每个点的后继点集合
    LinkedList *next[MAX_SIZE] = {NULL};
 
    // 记录图中点
    LinkedList *points = new_LinkedList();
    int occurs[MAX_SIZE] = {0};
 
    for (int i = 0; i < n; i++) {
        // 从 a 到 b 的路径
        int a, b;
        scanf("%d %d", &a, &b);
 
        // 收集图中所有节点
        if (!occurs[a]) {
            addLast_LinkedList(points, a);
            occurs[a] = 1;
        }
 
        if (!occurs[b]) {
            addLast_LinkedList(points, b);
            occurs[b] = 1;
        }
 
        // b点入度+1
        inDegree[b] += 1;
 
        if (next[a] == NULL) {
            next[a] = new_LinkedList();
        }
        // a点的后继点集合纳入b
        addLast_LinkedList(next[a], b);
    }
 
    // 图中总共total个节点
    int total = points->size;
    // head记录图的头节点
    int head = 0;
 
    // 队列记录入度为0的点
    LinkedList *queue = new_LinkedList();
 
    ListNode *cur = points->head;
    while (cur != NULL) {
        int p = cur->ele;
 
        // 题目描述中说图中只有一个首节点,首节点是入度为0的节点,因此如果某节点p没有入度,则为头节点
        if (inDegree[p] == 0) {
            head = p;
            addLast_LinkedList(queue, p);
            break;
        }
 
        cur = cur->next;
    }
 
    // tails记录所有尾节点
    int tails[MAX_SIZE];
    int tails_size = 0;
 
    // count记录已被剥去的点个数,如果图中存在环,则必然最终count < total
    int count = 0;
 
    while (queue->size > 0) {
        // 剥离入度为0的点
        int fa = removeFirst_LinkedList(queue);
        count++;
 
        // 如果fa没有后继点,即fa没有出度,则fa是尾节点
        if (next[fa] == NULL) {
            tails[tails_size++] = fa;
            continue;
        }
 
        // 如果fa有后继点,则其所有后继点入度-1
        ListNode *cur = next[fa]->head;
        while (cur != NULL) {
            int ch = cur->ele;
 
            inDegree[ch] -= 1;
 
            // 如果ch点入度变为0,则加入队列
            if (inDegree[ch] == 0) {
                addLast_LinkedList(queue, ch);
            }
 
            cur = cur->next;
        }
    }
 
 
    if (count != total) {
        // 如果存在环,则必然count < total
        printf("-1");
    } else {
        // 如果不存在环,则打印头节点和尾节点
        printf("%d ", head);
 
        // 注意本题描述存在冲突(用例2输出的尾节点是从小到大排序的,而题目输出描述是要求尾节点从大到小排序),这里以用例为准
        qsort(tails, tails_size, sizeof(int), cmp);
 
        for (int i = 0; i < tails_size; i++) {
            printf("%d", tails[i]);
 
            if (i < tails_size - 1) {
                printf(" ");
            }
        }
    }
 
 
    return 0;
}
  • 21
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值