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

来源:互联网 发布:html css js源码下载 编辑:程序博客网 时间:2024/06/03 21:46

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

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

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

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

def empty(q):    return len(q)==0def 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 4def 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 waitquedef 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 Trueprint(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 sumrecord = {}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,Nonedef 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