Codeforces 748 D Santa Claus and a Palindrome

来源:互联网 发布:java技术课程表 编辑:程序博客网 时间:2024/05/29 13:11

题目地址:http://codeforces.com/contest/748/problem/D
题意:告诉你一些字符串,和每个字符串的价值,让你求出一个价值最大的回文字符串
思路:其实特别简单,可是我读错了题,看成了最长的回文字符串,相等长度取价值最大的字符串。然后就顺利的wa了一天,今天早上重新读题才发现自己理解错了,好了废话不说了。其实就是把每个字符串分类成回文和非回文然后按价值排序。(详细看代码吧)

回文字符串可以做两边也可以做中心字符串
非回文字符串如果有可匹配的翻转串的话可以做两边的字符串

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <algorithm>#define N 100010#define LL long long #define inf 0x3f3f3f3fusing namespace std;map<string, int> mapp;vector<int> v1[N],v2[N];bool solve(string str) {//判断是不是回文字符串    for (int i = 0, j = str.length() - 1; i < j; i++, j--) {        if (str[i] != str[j])            return false;    }    return true;}bool cmp(int a, int b) {    return a > b;}int main() {    cin.sync_with_stdio(false);    int n, m;    string str;    int num, ans;    while (cin >> n >> m) {        ans = 0;        for (int i = 0; i < n; i++) {            cin >> str >> num;            if (mapp.find(str) == mapp.end()) {                mapp[str] = ans;                if (solve(str)) {                    v1[ans++].push_back(num);                }                else {                    v2[ans++].push_back(num);                }            }            else {                if (solve(str)) {                    v1[mapp[str]].push_back(num);                }                else {                    v2[mapp[str]].push_back(num);                }            }        }        for (int i = 0; i < ans; i++) {            if (v1[i].size()>1) {                sort(v1[i].begin(), v1[i].end(), cmp);            }            if (v2[i].size()>1) {                sort(v2[i].begin(), v2[i].end(), cmp);            }        }        int cnt = 0;        int size;        num = 0;        for (map<string, int>::iterator it = mapp.begin(); it != mapp.end(); it++) {            str = it->first;            int a = mapp[str];            reverse(str.begin(), str.end());//变成str的对称串            if (mapp.find(str) != mapp.end()) {                int b = mapp[str];                if (a == b) {//是回文的                    for (int i = 1; i < v1[a].size(); i += 2) {                        int kk = v1[a][i] + v1[a][i - 1];                        if (kk <= 0) {                            num = max(num, v1[a][i - 1]);                            break;                        }//如果这次为负数的话把前一个字符串的价值与最佳中心字符串的价值比对                        if (v1[a][i] < 0) {//如果这次后一个字符串的价值为负数的话把他后一个字符串的价值取负数与最佳中心字符串的价值比对(因为要最大所以如果最佳中心字符串也可以是原本加入的字符串不要做两边的而去做中心字符串,所以加上他两个对称字符串构成所损失的价值)                            num = max(num, -v1[a][i]);                        }                        cnt += kk;                    }                    if (v1[a].size() % 2) {                        num = max(num, v1[a][v1[a].size() - 1]);                    }//如果还有剩余的话可以做中心字符串                    v1[a].clear();                }                else {                    for (int i = 0; i < v2[a].size() && i < v2[b].size(); i++) {                        int kk = v2[a][i] + v2[b][i];                        if (kk <= 0) {//如果价值为负数直接抛弃                            break;                        }                        cnt += kk;                    }                    v2[a].clear();                    v2[b].clear();                }            }        }        cout << cnt + num << endl;    }    return 0;}