/**//* sample: ##-(##+###) 3333333 用下面的数字去填上面的#使得该式子最大 有多个时输出字典序最小的 首先,去括号 没有真的去掉,利用括号前的那些正负号来确定每个数字真实的正负号 为每个数字或者括号这样的整体添加正负号 如下面的例子 +(-(+a+b)+c) 这里在最外的括号及a也要有一个正号
为了转化出上面的式子用一个栈 1) '(' 如果其前面不是符号,就需要添加一个符号(跟栈顶一样) push(top) 2) '(' pop 3) '±' push(op^top) 这里把负号当成1 4) '#' 如果其前面不是符号就需要添加一个符号(跟栈顶一样) push(top) 然后连读 存起这个数 再pop 正数存在positive 负数存在negative
现在就来贪心 先将digit排序 对于正数,每次将digit里最大的数赋值给positive里长度最大的,或长度相同靠后的 对于负数,每次将digit里最小的数赋值给negative里长度最大的,或长度相同靠前的 可用一个堆来实现,取出后再放进去(这时长度少1了)
*/ #include<cstdio> #include<queue> #include<algorithm> #include<cstring> #include<stack> using namespace std;
const int MAXN = 210;
struct State { int len,pos,now; State(int len,int pos,int now):len(len),pos(pos),now(now){} bool operator<(const State &B)const //选长度长的,长度相同的话选位置靠后的 { if(len==B.len)return pos<B.pos; return len<B.len; } };
char str[MAXN],dig[MAXN];
int main() { //freopen("in","r",stdin); int T,t=1; for(scanf("%d",&T);T--;) { scanf("%s%s",str,dig); stack<int>S; S.push(0); priority_queue<State>positive,negative; for(int i=0;str[i];i++) { if(str[i]=='(') { if(i==0||str[i-1]=='(')S.push(S.top()); continue; } if(str[i]==')') { S.pop(); continue; } if(str[i]!='#') { S.push(S.top()^(str[i]=='-')); continue; } if(i==0||str[i-1]=='(')S.push(S.top()); int len = 0,start = i; while(str[i]=='#')i++,len++; i--; if(S.top())negative.push(State(len,-start,0));//-start 为了使前面的反而位置靠后 else positive.push(State(len,start,0)); S.pop(); } sort(dig,dig+strlen(dig)); int ans = 0; int beg=0,end=strlen(dig)-1; while(!positive.empty()) { State top=positive.top();positive.pop(); top.now=top.now*10+dig[end]-'0'; str[top.pos]=dig[end--]; top.pos++; top.len--; if(top.len==0)ans+=top.now; else positive.push(top); } while(!negative.empty()) { State top=negative.top();negative.pop(); top.now=top.now*10+dig[beg]-'0'; str[-top.pos]=dig[beg++]; top.pos--; top.len--; if(top.len==0)ans-=top.now; else negative.push(top); } printf("Case %d:\n",t++); puts(str); printf("%d\n",ans); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|