SCAU 1138 代码等式

本文介绍了一种解决特定形式的代码等式的算法。代码等式由二进制数0和1以及代表二进制串的小写字母组成。文章详细阐述了如何根据等式和变量长度来计算可能的解决方案数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1138 代码等式

时间限制:500MS  内存限制:65536K
提交次数:59 通过次数:21

题型: 编程题   语言: 无限制

Description

一个代码等式就是形如x1x2...xi=y1y2...yj,这里xi和yj是二进制的数字(0或1)或者是一个变量(如英语中的小写字母)。每一个变量都是一个有固定长度的二进制代码。例如:
a,b,c,d,e是变且它们的长度分别是4,2,4,4,2。考虑等式:1bad1=acbe,这个等式共有16组解。现要求任给一个等式,计算一共有多少组解。
(变量最多26个,长度和不超过10000)

输入格式

第一行数N为变量个数;
第二行N个数,为每个变量的位数
第三行为一个等式

输出格式

输出解的个数,无解输出0

输入样例

5
4 2 4 4 2
1bad1=acbe

 

输出样例

16

解题思路

题目意思:

代码由二进制数0,1和小写字母组成,其中字母代表若干个01二进制数,现在题目给你一个等式,等式也是有01和字母组成,然后告诉你用到字母的长度(二进制数的个数)根据等式判断满足等式的情况有多种

解题步骤:

个人的愚见一开始是用数组代表左右式子,根据字母的长度和已知的0和1分配到数组里,给每个数组里的元素记录信息,信息包括:所属的字母、在这个元素在字母中的排位,是否已经确认。前面两个信息是为了在接下来匹配等式两边的数时查找时要用到。而第三个信息点是为了在匹配当中和最后判断情况的时候用到确认这个元素是否是待定的。

开始时是以一个式子(默认为左式)为主式,从左到右扫,先根据已给的二进制扫,判断它的相同位置在副式(默认右式)中属于哪一个字母的那个位置,然后根据此查看牵动了多少其他元素的变动,变动主要分在这两个式子,所以我是分开判断,在此基础上,又开始在主和副式从左扫到右,根据情况再次变动,一直根据位置的变动判断元素的变动。最终停止的情况是找不到有相同所属字母和在字母中的排位(也就是一开始要存储得到前两点信息)

判断情况的时候是在上面的基础上进行的。也是手动将其中的元素变成已知。

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAXN 10010
typedef struct equation{
    int value, row, column;// value指是否已确认该值,row指所属的字母,column指排在的位置 
}equation;
equation left[MAXN], right[MAXN];
char input[MAXN];
int num[26], m;

int Transform(int cur, int kind)
{//根据kind的值仅是判断当前改变的在左式还是右式子 
    int i, j, flag;
    if(kind == 1 && right[cur].value == 0)
    {
        for(i=0; i<m; i++)
        {
            if(right[i].row == right[cur].row && right[i].column == right[cur].column && right[i].value == 0)
            {
                right[i].value = 1;
                Transform(i, 0);
            }
            if(left[i].row == right[cur].row && left[i].column == right[cur].column && left[i].value == 0)
            {
                Transform(i, 0);
            }
        }
    }
    else if(kind == 0 && left[cur].value == 0)
    {//下面的两个if可以当做两个for使用,一个元素的改变牵动左右两条式子,这里要做的就是及时更新信息 
        for(i=0; i<m; ++i)
        {
            if(left[i].row == left[cur].row && left[i].column == left[cur].column && left[i].value == 0)
            {
                left[i].value = 1;
                Transform(i, 1);
            }
            if(right[i].row == left[cur].row && right[i].column == left[cur].column && right[i].value == 0)
            {
                Transform(i, 1);
            }
        }
    }
    return 1;
}


int Before(int cur)
{
    int i;
    for(i=0; i<m; i++)
    {
        if(right[i].row == right[cur].row && right[i].column == right[cur].column && right[i].value == 0)
        {
            right[i].value = 1;
            Transform(i, 0);
        }
        if(left[i].row == right[cur].row && left[i].column == right[cur].column && left[i].value == 0)
        {
            Transform(i, 0);
        }
    }
}

int main()
{
//    freopen("input.txt", "r", stdin);
    int i, j, n, len, flag, buffer, str_left, str_right, cur_num, ans = 1, k;
    scanf("%d", &n);
    for(i=0; i<n; ++i)
        scanf("%d", &num[i]);
    scanf("%s", input);
    len = strlen(input);
    flag = strchr(input, '=') - input;
    k = m = str_left = str_right = 0;
    for(i=0; i<flag; ++i)
    {
        if(input[i] != '0' && input[i] != '1')
        {
            buffer = input[i] - 'a';
            m += num[buffer];
            for(j=0; j<num[buffer]; ++j,++str_left)
            {
                left[str_left].value = 0;
                left[str_left].row = buffer;
                left[str_left].column = j;
            }
        }
        else
        {
            left[str_left].value = 1;
            left[str_left].row = left[str_left].column = -1;
            str_left++;
            m++;
        }
    }
    //前后的两个for循环都是初始化信息 
    for(i=flag+1; i<len; ++i)
    {
        if(input[i] != '0' && input[i] != '1')
        {
            buffer = input[i] - 'a';
            k += num[buffer];
            for(j=0; j<num[buffer]; ++j, ++str_right)
            {
                right[str_right].value = 0;
                right[str_right].row = buffer;
                right[str_right].column = j;
            }
        }
        else
        {
            left[str_right].value = 1;
            left[str_right].row = right[str_right].column = -1;
            str_right++;
            k++;
        }
    }
    if(k != m)
    {//左右两式子的个数都不相同则表示无解 
        printf("0\n");
        return 0;
    }
    for(i=0; i<m; ++i)
    {
        if(left[i].row == left[i].column && left[i].row == -1)
            Transform(i, 1);
        if(right[i].row == right[i].column && right[i].row == -1)
            Transform(i, 0);
    }
    for(i=0; i<m; ++i)
    {//计算情况,before函数的作用就是为了模拟之前改动元素的情况,代码是直接复制的 
        if(left[i].value == 0)
        {
            ans *= 2;
            Before(i);
        }
    }
    for(i=0; i<m; ++i)
    {
        if(left[i].value != right[i].value)
        {
            printf("0\n");
            return 0;
        }
    }
    printf("%d\n", ans);
    return 0;
}

 



转载于:https://www.cnblogs.com/liaoguifa/p/3163971.html

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值