CF3D Least Cost Bracket Sequence(2500的实力贪心...

哎,昨天一直在赶课设。。没有写

最近听了一些人的建议,停止高级算法的学习,开始刷cf。

目前打算就是白天懒得背电脑的话,系统刷一遍蓝书紫书白书之类的(一直没系统刷过),回宿舍再上机吧。

https://www.luogu.org/problem/CF3D

题意:就是给你一个由 '(' , ')' , '?'组成的字符串,可以把'?'变成'('或')',但需要一定的代价,问使得括号匹配前提下的最小代价。

做法:贪心真的是个神奇的东东。。可以这么做,先从左扫到右,遇到'('就mark++,否则mark--(先把问号都当成右括号),如果是问号的话就顺便把它扔到优先队列,优先队列按-b+a排序,然后如果当前mark<0,就弹出个top(),给他变成左括号,优先队列为空说明无解。

#include<cstdio>
#include<queue>
using namespace std;
struct Data {        //优先队列的元素
    int delta;        //这是-b+a
    char *p;        //这是?的位置
    bool operator <(const Data &b)const {    //重定义比较运算符进行降序排列
        return delta>b.delta;
    }
}t;
priority_queue<Data> q;        //优先队列
char s[50002];
int main() {
    int mark=0;            //计数器
    long long ans=0;
    scanf("%s",s);
    for(int i=0,a,b;s[i]&&ans!=-1;++i) {
        if(s[i]=='(')    //计数器加1
            ++mark;
        else {
            --mark;        //计数器减1,'?'也一样,因为开始时设想所有的'?'都是')'
            if(s[i]=='?') {
                scanf("%d%d",&a,&b);
                t.delta=a-b;
                t.p=s+i;    //给指针赋值
                q.push(t);    //入队
                s[i]=')';
                ans+=b;
            }
        }
        if(mark<0) {        //此时要到前面去找'?'
            if(q.empty())
                ans=-1;        //如果队列为空,那么字符串不合法
            if(ans!=-1) {
                mark+=2;
                t=q.top();    //取队尾元素并替换
                q.pop();
                *t.p='(';
                ans+=t.delta;
            }
        }
    }
    if(mark)    //判断计数器是否为0,否则字符串不合法
        ans=-1;
    printf("%I64d",ans);    //用%I64d
    if(ans!=-1)
        printf("\n%s",s);
    return 0;
}

 

posted @ 2019-09-16 23:22  时光已随风而逝~  阅读(222)  评论(0编辑  收藏  举报