蓝桥杯 第六十四天 终极复习

不知不觉已经准备这么久了,希望明天好运

数位dp之k好数

盲猜会考数位dp,紧急复习一下

def dfs():
    global n
    num=[]
    while n!=0:
        num.append(n%k)
        n//=k
    ans=0
    last=-5
    for i in range(len(num)-1,-1,-1):
        x=num[i]
        for q in range(x):
            if abs(last-q)!=1:
                ans+=dp[i+1][q]
        if abs(last-x)==1:
            break
    print(ans)

k,l=map(int,input().split())
dp=[[0 for i in range(k)]for j in range(l+1)]
for i in range(k):
    for j in range(k):
        if abs(i-j)!=1:
            dp[2][i]+=1
for i in range(3,l+1):
    for j in range(k):
        for z in range(k):
            if abs(j-z)!=1:
                dp[i][j]+=dp[i-1][z]
n=0
for i in range(l):
    n+=(k-1)*pow(k,i)
dfs()

图论

dijkstra

def dijkstra():
    d=[1<<31 for i in range(n+1)]
    d[1]=0
    vis=[False for i in range(n+1)]
    for i in range(n):
        index=-1
        minlength=1<<31
        for j in range(1,n+1):
            if not vis[j] and d[j]<minlength:
                index=j
                minlength=d[j]
        if index==-1:
            return -1
        vis[index]=True
        for j in adj[index]:
            ne,va=j
            if not vis[ne] and d[ne]>d[index]+va:
                d[ne]=d[index]+va
    print(d[n])
n,m=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x].append((y,z))
dijkstra()

Bellman_Ford

要注意备份距离数组

判断不可到达时使用1<<30,应该可能被稍微更新一点

import copy


def bellman_ford():
    d=[1<<31 for i in range(n+1)]
    d[1]=0
    for i in range(k):
        dc=copy.deepcopy(d)
        for j in range(1,n+1):
            for z in adj[j]:
                ne,va=z
                if d[ne]>dc[j]+va:
                    d[ne]=dc[j]+va
    print(d[n])
n,m,k=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x].append((y,z))
bellman_ford()

SPFA

求最短路

def spfa():
    from collections import deque
    q=deque([])
    d=[1<<31 for i in range(n+1)]
    d[1]=0
    q.append(1)
    while q:
        top=q.popleft()
        for i in adj[top]:
            ne,va=i
            if d[ne]>d[top]+va:
                d[ne]=d[top]+va
                if ne not in q:
                    q.append(ne)
    print(d[n])
n,m=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x].append((y,z))
spfa()

判断负环

def spfa():
    flag=False
    from collections import deque
    q=deque([])
    d=[1<<31 for i in range(n+1)]
    d[1]=0
    q.append(1)
    num=[0 for i in range(n+1)]
    while q:
        top=q.popleft()
        for i in adj[top]:
            ne,va=i
            if d[ne]>d[top]+va:
                d[ne]=d[top]+va
                num[ne]+=1
                if num[ne]>n:
                    flag=True
                    break
                if ne not in q:
                    q.append(ne)
        if flag:
            break
    if flag:
        print("YES")
n,m=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x].append((y,z))
spfa()

floyd求最短路

def floyd():
    #初始化
    for i in range(1,n+1):
        adj[i][i]=0
    for k in range(1,n+1):
        for i in range(1,n+1):
            for j in range(1,n+1):
                adj[i][j]=min(adj[i][j],adj[i][k]+adj[k][j])
    return
n,m,k=map(int,input().split())
adj=[[1<<31 for i in range(n+1)]for j in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x][y]=z
floyd()
for i in range(k):
    x,y=map(int,input().split())
    if adj[x][y]>=1<<30:
        print("impossible")
    else:
        print(adj[x][y])

prim算法

def prim():
    d=[1<<31 for i in range(n+1)]
    d[1]=0
    vis = [False for i in range(n + 1)]
    ans=0
    for i in range(1,n+1):
        minlength=1<<31
        index=-1
        if not vis[i] and d[i]<minlength:
            minlength=d[i]
            index=i
        if index==-1:
            return False
        ans+=minlength
        vis[index]=True
        for j in adj[index]:
            ne,va=j
            if d[ne]>va:
                d[ne]=va
    print(ans)
n,m=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y,z=map(int,input().split())
    adj[x].append((y,z))
    adj[y].append((x,z))
prim()

kruskal算法

def find(x):
    if x!=fa[x]:
        fa[x]=find(fa[x])
    return fa[x]
n,m=map(int,input().split())
fa=[i for i in range(n+1)]
ans=0
for i in range(m):
    x,y,z=map(int,input().split())
    fax=find(x)
    fay=find(y)
    if fax!=fay:
        fa[fax]=fay
        ans+=z
print(ans)

染色法判断二分图

注意这个图可能不是联通的

def dfs(cur,fa,c):
    color[cur]=c
    for ne in adj[cur]:
        if ne!=fa:
            if color[ne]==0:
                if not dfs(ne,cur,3-c):
                    return False
            else:
                if color[ne]==color[cur]:
                    return False
    return True

n,m=map(int,input().split())
adj=[[]for i in range(n+1)]
for i in range(m):
    x,y=map(int,input().split())
    adj[x].append(y)
    adj[y].append(x)
flag=True
color=[0 for i in range(n+1)]
for i in range(1,n+1):
    if color[i]==0:
        if not dfs(i,-1,1):
            flag=False
            break
if flag:
    print("Yes")
else:
    print("No")

匈牙利算法

def dfs(cur):
    for i in a[cur]:
        if not st[i]:
            st[i]=True
            if right[i]==0 or dfs(right[i]):
              right[i]=cur#别漏了这个
                return True
            else:
                return False
    return False

n1,n2,k=map(int,input().split())
a=[[]for i in range(n1+1)]
b=[[]for i in range(n2+1)]
for i in range(k):
    x,y=map(int,input().split())
    a[x].append(y)
right=[0 for i in range(n2+1)]
ans=0
for i in range(1,n1+1):
    st=[False for i in range(n1+1)]
    if dfs(i):
        ans+=1
print(ans)

搜索

DFS

排列数

def dfs(cur,path):
    if len(path)==3:
        for i in path:
            print(i,end=" ")
        print()
        return
    for i in range(1,n+1):
        if not vis[i]:
            vis[i]=True
            dfs(i,path+[i])
            vis[i]=False
    return
n=int(input())
vis=[False for i in range(n+1)]
dfs(0,[])

n皇后问题

def isvalid(path,x):
    n=len(path)
    flag=True
    for i in range(n):
        if abs(n-i)==abs(x-path[i]):
            flag=False
            break
    return flag
def dfs(cur,a):
    if cur==n:
        print(a)
        return
    for i in range(n):
        if not a or (i not in a and isvalid(a,i))  :
            dfs(cur+1,a+[i])
    return
n=int(input())
dfs(0,[])

树的重心

BFS

走迷宫

def isvalid(x,y):
    if x<0 or x>=n:
        return False
    if y<0 or y>=m:
        return False
    if adj[x][y]==1:
        return False
    return True
dx=[1,-1,0,0]
dy=[0,0,1,-1]
def bfs():
    from collections import deque
    q=deque([])
    q.append(start)
    vis=[[False for i in range(m)]for j in range(n)]
    vis[0][0]=True
    ans=0
    while q:
        size=len(q)
        for i in range(size):
            top=q.popleft()
            if top==end:
                print(ans)
                return
            for i in range(4):
                nx,ny=top[0]+dx[i],top[1]+dy[i]
                if isvalid(nx,ny) and not vis[nx][ny]:
                    q.append((nx,ny))
                    vis[nx][ny]=True
        ans+=1

八数码

def isvalid(x,y):
    if x<0 or x>=3:
        return False
    if y<0 or y>=3:
        return False
    return True
dx=[1,-1,0,0]
dy=[0,0,1,-1]
def bfs():
    from collections import deque
    q=deque([])
    q.append(a)
    vis=dict()
    vis[a]=True
    ans=0
    while q:
        size=len(q)
        for i in range(size):
            top=q.popleft()
            if top==end:
                print(ans)
                return
            index=top.index('x')
            x=index//3
            y=index%3
            for j in range(4):
                nx,ny=x+dx[j],y+dy[j]
                if isvalid(nx,ny):
                    nindex=nx*3+ny
                    s=list(top)
                    s[index],s[nindex]=s[nindex],s[index]
                    s="".join(s)
                    if s not in vis:
                        vis[s]=True
                        q.append(s)
        ans+=1
    return

a="".join(input().split())
end="12345678x"
bfs()

数论

素数

def getprime():
    for i in range(2,N):
        if not vis[i]:
            vis[i]=True
            prime.append(i)
            pre[i]=i
        for j in prime:
            x=i*j
            if x>=N:
                break
            vis[x]=True
            pre[x]=j
            if i%j==0:
                break
N=100
prime=[]
vis=[False for i in range(N)]
pre=[-1 for i in range(N)]
getprime()
print(prime)

扩展欧几里得算法

def egcd(a,b):
    if b==0:
        return 1,0,a
    else:
        x,y,d=egcd(b,a%b)
        x,y=y,x-(a//b)*y
        return x,y,d
a,b=map(int,input().split())
x,y,d=egcd(a,b)
q=100
y*=q//d#放大一定倍数
a//=d#后面取余
y=y%a

更相损减法

def egcd(x,y):
    if x<y:
        x,y=y,x
    if y==1:
        return x
    else:
        return egcd(y,x//y)
x,y=map(int,input().split())
print(egcd(x,y))

动态规划

01背包问题

n,m=map(int,input().split())
v,w=[0],[0]
for i in range(n):
    vi,wi=map(int,input().split())
    v.append(vi)
    w.append(wi)
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(m+1):
        dp[i][j]=dp[i-1][j]
        if j>=v[i]:
            dp[i][j]=max(dp[i][j],w[i]+dp[i-1][j-v[i]])
print(dp[n][m])

完全背包问题

n,m=map(int,input().split())
v,w=[0],[0]
for i in range(n):
    vi,wi=map(int,input().split())
    v.append(vi)
    w.append(wi)
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(m+1):
        dp[i][j]=dp[i-1][j]
        if j>=v[i]:
            dp[i][j]=max(dp[i][j],w[i]+dp[i][j-v[i]])
print(dp[n][m])

多重背包

n,m=map(int,input().split())
v=[0]
w=[0]
for i in range(n):
    vi,wi,ki=map(int,input().split())
    num=1
    while ki>=num:
        v.append(vi*num)
        w.append(wi*num)
        ki-=num
        num*=2
    if ki!=0:
        v.append(vi*ki)
        w.append(wi*ki)
n=len(v)-1
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(m+1):
        dp[i][j]=dp[i-1][j]
        if j>=v[i]:
            dp[i][j]=max(dp[i][j],w[i]+dp[i-1][j-v[i]])
print(dp[n][m])

分组背包问题

n,m=map(int,input().split())
a=[[]for i in range(n+1)]
for i in range(1,n+1):
    x=int(input())
    for j in range(x):
        x,y=map(int,input().split())
        a[i].append((x,y))
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(m+1):
        dp[i][j]=dp[i-1][j]
        for k in a[i]:
            v,w=k
            if j>=v:
                dp[i][j]=max(dp[i][j],dp[i-1][j-v]+w)
print(dp[n][m])

数字三角形

n=int(input())
adj=[[-1<<31 for i in range(n+2)]for j in range(n+1)]
for i in range(1,n+1):
    a=list(map(int,input().split()))
    for j in range(len(a)):
        adj[i][j+1]=a[j]
for i in range(2,n+1):
    for j in range(1,i+1):
        adj[i][j]+=max(adj[i-1][j],adj[i-1][j-1])
print(max(adj[-1]))

最长上升子序列

n=int(input())
a=list(map(int,input().split()))
dp=[1 for i in range(n)]
for i in range(1,n):
    for j in range(i):
        if a[i]>a[j]:
            dp[i]=max(dp[i],dp[j]+1)
print(max(dp))

最长公共子序列

n,m=map(int,input().split())
a=" "+input()
b=" "+input()
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(1,m+1):
        if a[i]==b[j]:
            dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1)
        dp[i][j]=max(dp[i][j],dp[i-1][j],dp[i][j-1])
print(dp[n][m])

最短编辑距离

n=int(input())
a=" "+input()
m=int(input())
b=" "+input()
dp=[[0 for i in range(m+1)]for j in range(n+1)]
for i in range(1,n+1):
    for j in range(1,m+1):
        dp[i][j]=max(dp[i-1][j],dp[i][j-1])
        if a[i]==b[j]:
            dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1)
num=dp[n][m]
print(max(n,m)-num)

石子合并

n=int(input())
a=[0]+list(map(int,input().split()))
for i in range(1,n+1):
    a[i]+=a[i-1]
dp=[[1<<31 for i in range(n+1)]for j in range(n+1)]
for i in range(1,n+1):
    dp[i][i]=0
for k in range(1,n):
    for i in range(1,n):
        l=i
        r=i+k
        if r>n:
            break
        for j in range(l,r):
            dp[l][r]=min(dp[l][r],dp[l][j]+dp[j+1][r]+a[r]-a[l-1])
print(dp[1][n])

整数划分

n=int(input())
dp=[[0 for i in range(n+1)]for j in range(n+1)]
dp[0][0]=1
for i in range(1,n+1):
    for j in range(n+1):
        dp[i][j]+=dp[i-1][j]
        if j>=i:
            dp[i][j]+=dp[i][j-i]
print(dp[n][n])

蒙德里安的梦想

while True:
    n,m=map(int,input().split())
    st=[True for i in range(1<<n)]
    for i in range(1<<n):
        cnt=0
        flag=True
        for k in range(n):
            if i>>k&1==0:
                cnt+=1
            else:
                if cnt%2==1:
                    flag=False
                    break
                cnt=0
        if cnt%2==1:
            flag=False
        if not flag:
            st[i]=False
    dp=[[0 for i in range(1<<n)]for j in range(m+1)]
    dp[0][0]=1
    for i in range(1,m+1):
        for j in range(1<<n):
            for k in range(1<<n):
                if j&k==0 and st[j|k]:
                    dp[i][j]+=dp[i-1][k]
    print(dp[m][0])

最短哈密尔顿路径

n=int(input())
adj=[]
for i in range(n):
    adj.append(list(map(int,input().split())))
dp=[[1<<31 for i in range(1<<n)]for j in range(n)]
dp[0][1]=0
for j in range(1<<n):
    for i in range(n):
        if j>>i&1:
            for k in range(n):
                if (j-(1<<i))>>k&1:
                    dp[i][j]=min(dp[i][j],adj[k][i]+dp[k][j-(1<<i)])
print(dp[n-1][(1<<n)-1])

没有上司的舞会

def dfs(cur):
    ci,nci=a[cur],0
    for i in adj[cur]:
        x=dfs(i)
        ci+=x[1]
        nci+=max(x)
    return (ci,nci)
n=int(input())
a=[0]
for i in range(n):
    a.append(int(input()))
adj=[[]for i in range(n+1)]
st=[False for i in range(n+1)]
for i in range(n-1):
    l,k=map(int,input().split())
    st[l]=True
    adj[k].append(l)
fa=-1
for i in range(1,n+1):
    if not st[i]:
        fa=i
ans=dfs(fa)
print(max(ans))

滑雪

dx=[1,-1,0,0]
dy=[0,0,1,-1]
def isvalid(x,y):
    if x<0 or x>=n:
        return False
    if y<0 or y>=m:
        return False
    return True
def dfs(x,y):
    if dp[x][y]!=-1:
        return dp[x][y]
    cur=1
    for i in range(4):
        nx,ny=x+dx[i],y+dy[i]
        if isvalid(nx,ny) and adj[nx][ny]<adj[x][y]:
            cur=max(cur,dfs(nx,ny)+1)
    dp[x][y]=cur
    return cur
n,m=map(int,input().split())
adj=[]
for i in range(n):
    adj.append(list(map(int,input().split())))
ans=0
dp=[[-1 for i in range(m)]for j in range(n)]
for i in range(n):
    for j in range(m):
        if dp[i][j]==-1:
            ans=max(ans,dfs(i,j))
print(ans)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值