欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

华为 OD 机测试 - Excel 单元格值统计(Python/JS/C/C++ 2024 年 E 卷 200 分) - VIII、C 算法源代码

最编程 2024-10-06 21:03:03
...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_ROWS 20
#define MAX_COLS 26
#define MAX_CELL_LEN 100
#define MAX_EXPR_LEN 1000

// 定义表格内容
char table[MAX_ROWS][MAX_COLS][MAX_CELL_LEN];
// 记忆化存储单元格值,初始化为未计算状态
long long memo_val[MAX_ROWS][MAX_COLS];
int memo_flag[MAX_ROWS][MAX_COLS] = {0};

// 表格的行数和列数
int rows, cols;

// 将单元格标识转换为行列索引
void cell_to_index(char *cell, int *row, int *col){
    *col = 0;
    int i = 0;
    // 处理列(字母部分)
    while(cell[i] && isalpha(cell[i])){
        *col = (*col) * 26 + (toupper(cell[i]) - 'A' + 1);
        i++;
    }
    // 处理行(数字部分)
    char num_part[MAX_CELL_LEN];
    int j = 0;
    while(cell[i]){
        num_part[j++] = cell[i++];
    }
    num_part[j] = '\0';
    *row = atoi(num_part) -1;
    *col = *col -1;
}

// 将行列索引转换为单元格标识
void index_to_cell(int row, int col, char *cell){
    cell[0] = '\0';
    col +=1;
    char temp[10];
    while(col >0){
        int rem = (col -1) %26;
        char c = 'A' + rem;
        sprintf(temp, "%c", c);
        strcat(cell, temp);
        col = (col -1) /26;
    }
    char row_str[10];
    sprintf(row_str, "%d", row +1);
    strcat(cell, row_str);
}

// 解析并计算表达式
long long evaluate_expression(char *expr);

// 解析单个项,可能是单元格引用或数字
long long parse_term(char *term){
    if(isalpha(term[0])){
        int r, c;
        cell_to_index(term, &r, &c);
        return evaluate(r, c);
    }
    else{
        return atoll(term);
    }
}

// 计算单元格的值
long long evaluate(int row, int col){
    // 如果已经计算过,直接返回
    if(memo_flag[row][col]){
        return memo_val[row][col];
    }
    char *content = table[row][col];
    long long value =0;
    if(content[0] != '='){
        // 直接是数字
        value = atoll(content);
    }
    else{
        // 是公式,解析并计算表达式
        char expr[MAX_EXPR_LEN];
        strcpy(expr, content +1); // 去掉 '='
        value = evaluate_expression(expr);
    }
    // 记忆化存储
    memo_val[row][col] = value;
    memo_flag[row][col] =1;
    return value;
}

// 解析并计算表达式
long long evaluate_expression(char *expr){
    int op_pos = -1;
    char op = 0;
    // 查找运算符的位置
    for(int i=0; i<strlen(expr); i++){
        if(expr[i] == '+' || expr[i] == '-'){
            op_pos = i;
            op = expr[i];
            break;
        }
    }
    if(op_pos == -1){
        // 没有运算符,可能是单元格引用或数字
        char term[MAX_CELL_LEN];
        strcpy(term, expr);
        return parse_term(term);
    }
    else{
        // 分割表达式为左半部分和右半部分
        char left[MAX_CELL_LEN];
        strncpy(left, expr, op_pos);
        left[op_pos] = '\0';
        char right[MAX_CELL_LEN];
        strcpy(right, expr + op_pos +1);
        long long left_val = parse_term(left);
        long long right_val = parse_term(right);
        if(op == '+'){
            return left_val + right_val;
        }
        else{
            return left_val - right_val;
        }
    }
}

int main(){
    // 读取行数和列数
    scanf("%d %d", &rows, &cols);
    // 读取表格内容
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            scanf("%s", table[i][j]);
        }
    }
    // 读取统计区域
    char range[20];
    scanf("%s", range);
    // 解析统计区域的起始和结束单元格
    char *token = strtok(range, ":");
    char start_cell[MAX_CELL_LEN];
    char end_cell[MAX_CELL_LEN];
    strcpy(start_cell, token);
    token = strtok(NULL, ":");
    strcpy(end_cell, token);
    int start_r, start_c, end_r, end_c;
    cell_to_index(start_cell, &start_r, &start_c);
    cell_to_index(end_cell, &end_r, &end_c);
    // 计算总和
    long long total =0;
    for(int r=start_r; r<=end_r; r++){
        for(int c=start_c; c<=end_c; c++){
            total += evaluate(r, c);
        }
    }
    // 输出结果
    printf("%lld\n", total);
    return 0;
}