CSP202009-3点亮数字人生(Python题解)

一、用字典将器件的FUNC转化为数字

二、维护三个数据列表,输入信号列表input_list=[I1, I2, I3, ..., Im],每个器件的输出值列表out_list=[O1, O2, ..., On],器件信息列表unit_list=[(功能号, [输入信号1, ...,输入信号s])]。out_list与unit_list的元素有对应关系。

三、代码运行逻辑为,遍历器件信息列表unit_list,如果有能算的器件,就算出该器件的输出,并写入out_list。遍历器件信息列表若干遍后,所有能算出输出值的器件都会被算出来写到out_list中。根据题目要求查询out_list得到题目要的器件的输出。

四、如何判环?把unit_list遍历一遍,得到一个类似校验码的值,程序中为变量MD5(并不是真的MD5码,就是顺口叫的),若再遍历一遍unit_list,其元素全都没变,表现为MD5值不变,就说明没有可以算的原件了。这时若有原件还是没有被计算过,说明其输入值根本不可得,即有循环。这一点在程序中表现为能算的都算了,out_list中竟然还记录有的原件输出为-1。-1为out_list元素初始值。

五、注意1和0的逻辑运算,~0=-1,~1=-2,要想实现0和1的相互转化应该用not 1=0,not 0=1



mapping={'NOT':0,'AND':1,'OR':2,'XOR':3,'NAND':4,'NOR':5}

Q=int(input().strip())
for q in range(Q):
    M,N=map(int,input().strip().split())

    unit_list=[]
    for i in range(N):
        temp=input().strip().split()
        ttemp=[]
        for j in range(2,len(temp)):
            chars=temp[j]
            if chars[0]=='I':
                ttemp.append(int(chars[1:]))
            else:
                ttemp.append(-1*int(chars[1:]))
        unit_list.append((mapping[temp[0]],ttemp))

    S=int(input().strip())
    input_list=[]
    for i in range(S):
        input_list.append(list(map(int,input().strip().split())))
    out_index_list=[]
    for i in range(S):
        out_index_list.append(list(map(int,input().strip().split()[1:])))

    out_list=[[-1 for i in range(N)] for j in range(S)]

    def cal_able(iindex,epoch):
        _,coefs=unit_list[iindex]
        for i in coefs:
            if i <0 and out_list[epoch][-1*i-1]==-1:
                return False
        return True

    def cal(iindex,nums,epoch):
        ttype,_=unit_list[iindex]
        if ttype==0:
            out_list[epoch][iindex]=int(not nums[0])
        elif ttype==1:
            temp=1
            for num in nums:
                temp=temp&num
            out_list[epoch][iindex]=temp
        elif ttype==2:
            temp=0
            for num in nums:
                temp=temp|num
            out_list[epoch][iindex]=temp
        elif ttype==3:
            temp=nums[0]
            for i in range(1,len(nums)):
                temp=temp^nums[i]
            out_list[epoch][iindex]=temp
        elif ttype==4:
            temp=1
            for num in nums:
                temp=temp&num
            out_list[epoch][iindex]=int(not temp)
        elif ttype==5:
            temp=0
            for num in nums:
                temp=temp|num
            out_list[epoch][iindex]=int(not temp)

    def calculate(iindex,epoch):
        _,coefs = unit_list[iindex]
        nums=[]
        for i in coefs:
            if i>0:
                nums.append(input_list[epoch][i-1])
            else:
                nums.append(out_list[epoch][-1*i-1])
        cal(iindex,nums,epoch)



    for epoch in range(S):
        old_MD5=0
        new_MD5=sum(out_list[epoch])
        while old_MD5!=new_MD5:
            old_MD5=new_MD5

            for i in range(len(unit_list)):
                if cal_able(i,epoch):
                    calculate(i,epoch)
        
            new_MD5=sum(out_list[epoch])

    dlt=1
    for epoch in range(S):
        if -1 in out_list[epoch]:
            print('LOOP')
            dlt=0
            break
    if dlt:
        for epoch in range(S):
            for i in out_index_list[epoch]:
                print(out_list[epoch][i-1], end=' ')
            print()

仍有可以优化的地方,懒得优化了,跑了93ms,还行。

欢迎提建议。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值