填数【C语言】

题目描述#

有个格子,其中所有偶数格已经被填上了+或者-,现在请你将 填入剩余的格子,所有格子都必须填数,每个格子都只能填一个数,且所有数都只能使用一次。

要使得填完以后的算术表达式的结果为,请你给出一个填数方案。

输入格式#

第一行是一个整数,表示样例的个数。

每个样例的第一行是一个整数,表示需要填的数。

第二行是个由+,-组成的字符串。

输出格式#

依次输出样例的结果。

如果存在填数的方案,输出个数,表示填入的数。

否则,输出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;
}
相关推荐
天空'之城5 小时前
C 语言工业级通用组件手写 24:互补滤波
c语言·开发语言·互补滤波·嵌入式算法·工业级组件
stevenseahang13 小时前
C语言标准演化史:从K&R到GNU,谁才是正统?
c语言·gnu·可移植性·标准演化·ansic
别动我齐刘海14 小时前
Day6 unitree_G1人形机器人GMR—— MotionInput
c语言·c++·人工智能·学习·机器学习·机器人·github
AI科技星14 小时前
曲率‑挠率与 $\boldsymbol{\omega/c}$ 的关系、精算验证及其物理意义
c语言·开发语言·线性代数·算法·决策树·机器学习·ai科技星
坏柠18 小时前
C语言进阶:从零实现一个可靠的环形缓冲区,吃透回绕、边界与并发
java·c语言·算法
choumin18 小时前
C程序能调用extern “C“声明的带默认参数的C++函数吗?
c语言·c++·extern c·默认参数
LONGZETECH18 小时前
传统实训 vs 仿真实训:从技术架构拆解新能源汽车教学的范式之变
c语言·3d·unity·架构·汽车
白白白小纯19 小时前
每日算法day3—回文链表,链表分割
c语言·数据结构·算法·leetcode
Aurorar0rua19 小时前
CS50 x 2024 Notes Algorithms - 08
c语言·开发语言·算法·学习方法
✎ ﹏梦醒͜ღ҉繁华落℘19 小时前
单片机基础知识--LVGL学习-lv_obj_add_flag()
c语言·单片机·学习