算法竞赛入门经典:第6章例题

例题1:模拟并行程序的运行,采取双端队列来运行。主要考虑到以下几个逻辑问题:

(1) 首先要注意当前剩下的时间是不是还够运行该条命令。不够的话就要结束当前的循环且不能删除该条命令。即便是end命令可能也不够时间完成!

(2) 如果该程序是正常结束,就不要将该命令入队列,或者如果该命令是因为被锁住而退出循环,也不能入队列。注意不能用剩余时间来判断,因为有可能使执行lock命令之后时间刚好为0,然后才被退出循环的。如果一定要用剩余时间来判断,就应该将这个减去剩余时间的执行放在if分支的最后执行。

(3) 注意执行完unlock以后要把阻止队列的任务放出来

def empty(q):
    return len(q)==0
def get_from_print(code):
    cmd = code.split(' ')
    return Value[cmd[1]]
def get_var(code):
    cmd = code.split(' ')
    return cmd[0],cmd[2]
def Type(code):
    if   code=='lock':return 0
    elif code=='unlock':return 1
    elif code[0:3]=='end':return 2
    elif code[0:5]=='print':return 3
    else:return 4
def process(n,t,Q):
    print(t)
    programs_left = n
    index = 1
    while programs_left != 0:
        line = input()
        if line[0:3]=='end':p[index].append(line);index+=1;p[index] = [];programs_left-=1;continue
        p[index].append(line)#put the input into the p[index]
    for i in range(n):waitque.append(i+1)
    islocked = False
    while not empty(waitque):
        program = waitque.popleft()
        remainder = Q
        blocked = False
        while remainder > 0:
            code = p[program][0]
            code_type = Type(code)
            #print('case:',program,'codetype******',code_type,code)
            if code_type == 0:#.....................lock
                if remainder>= t[code_type]:remainder -= t[code_type]
                else:break# no enough time to run the cmd
                if not islocked: 
                    islocked = True
                else:
                    blocked = True
                    blockque.append(program)#put program into the blockque
                    break#.........................would not delete the code beacuse it failed
            elif code_type == 1 :#..................unlock
                if remainder>= t[code_type]:remainder -= t[code_type]
                else:break# no enough time to run the cmd
                islocked = False
                if not empty(blockque):
                    another_program = blockque.popleft()
                    waitque.appendleft(another_program)#put another_program into the first of waitque
            elif code_type == 2:#...................end
                if remainder>= t[code_type]:remainder -= t[code_type]
                else:break# no enough time to run the cmd
                remainder = 0
            elif code_type == 3:#.......................print
                if remainder>= t[code_type]:remainder -= t[code_type]
                else:break# no enough time to run the cmd
                var = get_from_print(code)
                print(program,':',var)#output program,the value of var
            else :#.....................................assignment
                if remainder>= t[code_type]:remainder -= t[code_type]
                else:break# no enough time to run the cmd
                var,constant = get_var(code)
                Value[var] = constant
            p[program].remove(code)#delte the code which has been run
        if not empty(p[program]) and not blocked:
            waitque.append(program)#put program into the end of waitque
def get_args():
    line = input()
    line = line.split(' ')
    n,t1,t2,t3,t4,t5,Q = line
    n,t,Q = int(n),[int(t1),int(t2),int(t3),int(t4),int(t5)],int(Q)
    return [n,t,Q]
process(*get_args())

62 :典型的栈的运用,从出去的顺序入手,对于每一个元素,都将所有比它小的元素入一个新的栈,假如发现一个入栈的结果不等于当前的目标同样位置的元素,则不可以。

def test(enter,depart):
    i,k,n = 1,0,len(depart)
    new = []
    while k<n:
        new_items = 1
        new.append(depart[k])
        while i<n:
            if i==depart[k]:i+=1;break
            new.append(i)#push i into new
            if new[i]!=depart[i]:return False
            i+=1
            new_items += 1
        k+= new_items
    return True
print(test([1,2,3,4,5],[5,4,1,2,3]))

63 :利用栈来求表达式,矩阵链乘

def matrix(expression):
    def times(a,b):
        return a[0]*b[0]*b[1]
    def mul(a,b):
        return (a[0],b[1])
    def ok(a,b):
        return a[1]==b[0]
    sum,s=0,[]
    for each in expression:
        if each.isalpha():s.append(record[each]);print(each,s)
        elif each==')':
            b = s.pop()
            a = s.pop()
            if ok(a,b):s.append(mul(a,b));sum+=times(a,b);print(s,times(a,b))
            else:return 'error'
    if len(s)!=1:
        sum += times(s[1],s[0])
    return sum
record = {}
def process():
    n = int(input())
    while n>0:
        line = input()
        line = line.split(' ')
        record[line[0]] = (int(line[1]),int(line[2]))
        n-=1
    while 1:
        exp = input()
        if exp=='':break
        print(matrix(exp))
process()

64 悲剧的键盘,这个题目的关键是不能用数组插入,因为插入会引起大量的移动最终导致超时。方法是利用链表来解决问题,这里的链表不是实际意义的链表,只是利用数组模拟的链表。构造一个next数组,其中next[i]代表字符i右边是哪个字符!为了方便起见,虚拟一个next[0]代表最左边的字符,用一个last来标志当前的最后一个字符的位置,curr代表当前光标的位置(也是要插入的位置)。

def proc2():
    line = ' '+input()
    while line!='':
        curr,last=0,0
        next = [0]*(len(line)+5)
        for i,ch in enumerate(line):
            if ch=='[':curr=0
            elif ch==']':curr=last
            else:#simulate the insert operation 
                next[i] = next[curr]
                next[curr] = i
                if curr==last:last=i#update the last
                curr = i
        i = next[0]
        print(next)
        while i!=0:
            print(line[i],end='')
            i = next[i]
        print()
        line = input()
proc2()

65 这道题目有点难度,主要是调试起来很麻烦,根据答案进行了一定优化,得到下面代码.

(a): 注意采取了双向链式的结构

(b): 一定要区分交换节点这个操作如果两节点相邻要特殊对待,同时相邻的方式不同,处理方式不同。在这里采取只处理一种相邻的方式,另一种可以通过交换x,y转化。

(c): 注意采取了特殊的方式来处理反转这个操作,因为这个操作很消耗时间,用一个标记来处理而不真正执行。但是要注意 1,x,y在逆转状态下变成了2,x,y,这招略trick。

(d): 构造辅助函数link(x,y),减少代码量。注意到,其实删除一个节点等价于link(p_x,n_x)。想到这一点就容易减少代码


def Get(cmd):
    cmd = cmd.split(' ')
    if len(cmd)==3:
        return int(cmd[0]),int(cmd[1]),int(cmd[2])
    else:
        return 4,None,None
def proc(n,cmds):
    next =[i+1 for i in range(n+5)]
    pre = [i-1 for i in range(n+5)]
    rev = 0
    def link(L,R):
        next[L],pre[R] = R,L
    for cmd in cmds:
        Type,x,y = Get(cmd)
        if rev==1 and Type<2:Type = 3-Type
        if Type==3 and next[y]==x:x,y = y,x
        if x and y:p_x,p_y,n_x,n_y = pre[x],pre[y],next[x],next[y]
        if Type == 2:#right
            if not next[y]==x:#x is not in the right of y:,
                link(p_x,n_x);link(y,x);link(x,n_y)
        elif Type == 1:#left
            if not next[x]==y:
                link(p_y,x);link(x,y);link(p_x,n_x)
        elif Type == 3:
            if not next[x]==y:
                link(p_x,y);link(y,n_x);link(p_y,x);link(x,n_y)
            else:
                link(p_x,y);link(y,x);link(x,n_y)
        else:#reverse all the list
            rev = 1
    sum,i,first = 0,1,next[0]
    while i<=n:
        if (n-i+1 if rev else i)%2==1:sum+=first
        first,i= next[first],i+1
    print(sum)
def func():
    line = input()
    while line!='':
        cmds = []
        line = line.split(' ')
        n,num = int(line[0]),int(line[1])
        line
        while num:
            cmd = input()
            cmds.append(cmd)
            num-=1
        proc(n,cmds)
        line = input()
func()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
软件名称: 题海泛舟 软件版本: 1.0 软件作者: ccamp 作者邮件: ilovebd@263.net 软件网站: http://ccampsoft.yeah.net 下载地址: http://www.freewebz.com/ccamp/tihai.exe http://tj.skycn.net/down/tihai.exe 软件容量: 5.84M 软件语言: 简体中文 授权形式: 共享 应用平台: WIN98/NT/ME/2000 发布日期: 2002年3月5日 软件介绍: 软件简介: 随着信息化社会的发展,越来越多的教师和教育工作者开始使用计算机来辅助教学。用计算机来出考试试卷就是其中重要的一项。然而,输入题目的烦琐,查找题目的困难,这些使得使用计算机出卷变的费时费力,甚至还不如手写来得快速。 题海泛舟正是一个旨在解决上述问题的试题库软件。它集成了试题编辑、题库管理、抽取试卷等功能,非常适合与教师个人或学校使用。它可以使出卷变的真正轻松快捷。 功能特点: 支持多用户,使得不同题库间的管理变的简单容易,尤其适合在学校使用。 软件界面清新典雅,并可以更换界面,使您在工作时保持良好心情。 多种方式的录入题目方式,与WORD紧密结合,具有拖入窗口和强大的批量录入题目功能,使得录入题目高效轻松。 强大的查询功能,可以根据各种属性查询题目。 一目了然的树型目录显示题目,同时具有题目列表,并支持分类显示题目,使的管理查看题目轻而易举。 具有题目收藏功能,快速访问收藏题目。 快速插入符号公式上下标,并具有特色的插入自定义文字功能,可以简单输入如“Na2CO3";;;这样的复杂文字。 手动抽取题目只需拖动,并可以直接拖动类别。 随机抽取题目功能强大,支持难度分布组卷。 形成试卷选项多样,并具有试卷模版,可以直接保存为WORD文件。 备份,压缩,合并题库高效快速。 批量抽取试卷,一次抽取N份

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值