 /**//*
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
搜索
最新评论

|
|