1 条题解

  • 0
    @ 2025-5-19 19:03:03

    算法思想

    首先预处理书名,提取纯字母序列并按字典序排序;然后采用动态规划,定义状态dp[j][k]表示选j本书且最后一本为第k本时的最大价值,通过遍历已选数量、当前书籍和前一本书,检查字符冲突后更新状态;接着利用前驱数组回溯选取的书籍索引;最后按要求输出数量、总价值和书名。核心是通过动态规划处理约束条件下的组合优化,利用预处理和有序性提升效率。

    代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <cctype>
    #include <climits>
    #include <map>
    #include <sstream>
    
    using namespace std;
    
    struct Book {
        int value;
        string title;
        string normalized;
    };
    
    vector<Book> books;
    vector<vector<int> > dp;
    vector<vector<int> > prev_book;
    int max_total = 0;
    vector<int> best_sequence;
    
    // 预处理标题,移除非字母字符并转为小写
    string normalize_title(const string& title) {
        string normalized;
        for (size_t i = 0; i < title.size(); ++i) {
            char c = title[i];
            if (isalpha(c)) {
                normalized += tolower(c);
            }
        }
        return normalized;
    }
    
    // 检查两个标准化后的标题是否有相同位置的相同字母
    bool has_conflict(const string& a, const string& b) {
        int len = min(a.size(), b.size());
        for (int i = 0; i < len; ++i) {
            if (a[i] == b[i]) {
                return true;
            }
        }
        return false;
    }
    
    // 比较函数对象,用于排序
    struct BookCompare {
        bool operator()(const Book& a, const Book& b) const {
            return a.title < b.title;
        }
    };
    
    void solve() {
        int n = books.size();
        if (n == 0) return;
    
        // 按标题排序
        sort(books.begin(), books.end(), BookCompare());
    
        // 初始化DP表
        dp.assign(n, vector<int>(10, 0));
        prev_book.assign(n, vector<int>(10, -1));
    
        // 初始状态:每本书单独作为序列的第一个
        for (int i = 0; i < n; ++i) {
            dp[i][0] = books[i].value;
        }
    
        // 动态规划填表
        for (int i = 1; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (!has_conflict(books[j].normalized, books[i].normalized)) {
                    for (int k = 0; k < 9; ++k) {
                        if (dp[j][k] > 0 && dp[j][k] + books[i].value > dp[i][k+1]) {
                            dp[i][k+1] = dp[j][k] + books[i].value;
                            prev_book[i][k+1] = j;
                        }
                    }
                }
            }
        }
    
        // 找到最大值
        max_total = 0;
        int last_book = -1, last_pos = -1;
        for (int i = 0; i < n; ++i) {
            for (int k = 0; k < 10; ++k) {
                if (dp[i][k] > max_total) {
                    max_total = dp[i][k];
                    last_book = i;
                    last_pos = k;
                }
            }
        }
    
        // 回溯找到序列
        best_sequence.clear();
        while (last_book != -1 && last_pos >= 0) {
            best_sequence.push_back(last_book);
            last_book = prev_book[last_book][last_pos];
            last_pos--;
        }
        reverse(best_sequence.begin(), best_sequence.end());
    }
    
    int string_to_int(const string& s) {
        istringstream iss(s);
        int value;
        iss >> value;
        return value;
    }
    
    int main() {
        int N;
        cin >> N;
        cin.ignore(); // 忽略第一行后面的换行符
    
        for (int i = 0; i < N; ++i) {
            string line;
            getline(cin, line);
            
            size_t space_pos = line.find(' ');
            int value = string_to_int(line.substr(0, space_pos));
            string title = line.substr(space_pos + 1);
            
            string normalized = normalize_title(title);
            Book book;
            book.value = value;
            book.title = title;
            book.normalized = normalized;
            books.push_back(book);
        }
    
        solve();
    
        // 输出结果
        cout << best_sequence.size() << endl;
        cout << max_total << endl;
        for (size_t i = 0; i < best_sequence.size(); ++i) {
            cout << books[best_sequence[i]].title << endl;
        }
    
        return 0;
    }
    
    • 1

    信息

    ID
    1512
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者