题目描述#
有个格子,其中所有偶数格已经被填上了+或者-,现在请你将 填入剩余的格子,所有格子都必须填数,每个格子都只能填一个数,且所有数都只能使用一次。
要使得填完以后的算术表达式的结果为,请你给出一个填数方案。
输入格式#
第一行是一个整数,表示样例的个数。
每个样例的第一行是一个整数,表示需要填的数。
第二行是个由+,-组成的字符串。
输出格式#
依次输出样例的结果。
如果存在填数的方案,输出个数,表示填入的数。
否则,输出impossible 。
样例输入#
2
3
+-
4
++-
样例输出#
1 2 3
impossible
思路说明

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int compare(const void*a, const void*b){
return strcmp((const void*)a,(const void*)b);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int n;
char s[1001];
scanf("%d",&n);
scanf("%s",s);
long long sum=(long long)n*(n+1)/2;
if(sum%2!=0){
printf("impossible\n");
continue;
}
long long sum_half=sum/2;
int m=0;
for(int i=0;i<n-1;i++){
if(s[i]=='+')m++;
}
int m_plus_1=m+1;//加法元素个数
long long min_sum=(long long)m_plus_1*(m_plus_1+1)/2;
long long max_sum=sum-(long long)(n-m_plus_1)*(n-m_plus_1+1)/2;
if(sum_half<min_sum || sum_half>max_sum){
printf("impossible\n");
continue;
}
int add[m_plus_1];//构造加法集合
for(int i=0;i<m_plus_1;i++)
add[i]=i+1;
long long delta=sum_half-min_sum;
int avg=delta/m_plus_1;
int rem=delta%m_plus_1;
for(int i=0;i<m_plus_1;i++)
add[i]+=avg;
for(int i=m_plus_1-1;i>=m_plus_1-rem;i--)
add[i]++;
qsort(add,m_plus_1,sizeof(int),compare);
int subtract[n-m_plus_1];//构造减法集合
int sub_idx=0;
int used[n+1]; //标记数组
memset(used,0,sizeof(used));
for(int i=0;i<m_plus_1;i++)
used[add[i]]=1;
for(int i=1;i<=n;i++){
if(!used[i]){
subtract[sub_idx++]=i;
}
}
qsort(subtract,sub_idx,sizeof(int),compare);
int add_ptr=0,sub_ptr=0;
printf("%d",add[add_ptr++]);
for(int i=0;i<n-1;i++){
if(s[i]=='+'){
printf(" %d",add[add_ptr++]);
}else{
printf(" %d",subtract[sub_ptr++]);
}
}
printf("\n");
}
return 0;
}