SCAU 1138 代码等式

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SCAU编译综合性实验是指在南京农业大学计算机学院进的综合性实践课程,旨在培养学生在编译原理方面的实际能力。该实验要求学生利用所学知识和技能,设计并实现一个基于某种编程语言的编译器。 在实验开始前,学生需要深入学习编译原理相关知识,包括词法分析、语法分析、语义分析、中间代码生成和目标代码生成等。同时,他们还需要掌握常用编译器工具,例如flex、bison等。 实验内容包括以下主要步骤: 1. 语法分析:根据给定的文法规则,设计并实现语法分析器。通过分析源代码的结构,并生成相应的语法树。 2. 语义分析:在语法分析的基础上,进一步检查和分析源代码的语义是否符合规范。例如,检查变量声明是否正确、类型是否匹配等。 3. 中间代码生成:将源代码翻译成中间代码,比如三地址码或四元式。中间代码是一种与具体机器无关的表示方式,可以方便地进优化和后续的目标代码生成。 4. 目标代码生成:将中间代码翻译成目标机器上可执的机器代码。这个过程需要考虑不同机器指令集的特点和限制,以及优化生成的目标代码。 5. 目标代码优化:对生成的目标代码优化,使其在运效率和内存占用上更加优化。 6. 调试和测试:通过合适的测试用例检验编译器功能的正确性和性能。同时,对编译器进调试,决可能出现的错误和问题。 7. 实验报告:撰写实验报告,详细描述实现的过程、方法、结果和分析。 综合性实验的完成需要良好的编程能力和分析问题的能力。通过这个实验,学生不仅巩固了编译原理相关知识,还培养了决实际问题的能力和团队合作精神。这对今后从事软件开发和计算机研究工作都具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值