学python的第十三天---小蓝(4)

贪心

在这里插入图片描述
在这里插入图片描述

1、活动安排问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、区间覆盖问题

在这里插入图片描述
在这里插入图片描述

3、最优装载问题

在这里插入图片描述

4、多机调度问题

在这里插入图片描述

一、答疑(贪心)

在这里插入图片描述
在这里插入图片描述
关键是列出通式!

n=int(input())
q=[]
for i in range(n):
    s,a,e=map(int,input().split())
    q.append((s,a,e,s+a+e))
q.sort(key =lambda x:x[3])
res=0
for i in range(0,n-1):
    res+=(n-i-1)*q[i][3]+q[i][0]+q[i][1]
res+=q[n-1][0]+q[n-1][1]
print(res)

二、巧克力(贪心)

在这里插入图片描述
有一个点运行超时了

n, kind = map(int, input().split())
all_list = []
for i in range(kind):
   info_list = [int(i) for i in input().split(' ')]
   all_list.append(info_list)
all_list.sort(key=lambda x: x[0])


def solve(n, all_list):
   c = 0
   days = [i for i in range(1, n+1)]
   days = sorted(days, reverse=True)
   for i in days:
       tmp_c = 0
       for j in all_list:
           if j[2] > 0:
               if j[1] >= i:
                   tmp_c += j[0]
                   index = all_list.index(j)
                   all_list[index][2] -= 1
                   break
       if tmp_c == 0:
           return -1
       else:
           c += tmp_c
   return c


print(solve(n, all_list))

三、顺子日期(模拟)

在这里插入图片描述

mon=[0,31,28,31,30,31,30,31,31,30,31,30,31]
def check(s):
    if "012" in s:
        return True
    if "123"in s:
        return True
    return False

res=0
s="2022"
for i in range(1,12+1):
    for j in range(1,mon[i]+1):
        if i<10:
            ss=s+"0"+str(i)
        else:
            ss=s+str(i)
        if j<10:
            ss=ss+"0"+str(j)
        else:
            ss=ss+str(j)
        if check(ss):
            # print(ss)
            res+=1
print(res)

四、特殊时间(模拟)

在这里插入图片描述


day_per_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
#检查日期D是否合法
def check_D(D):
    month = D // 100
    day = D % 100
    if month < 1 or month > 12:
        return 0
    if day < 1 or day > day_per_month[month]:
        return 0
    return 1
#检查时刻H是否合法
def check_H(H):
    h = H // 100
    m = H % 100
    if h < 0 or h > 23:
        return 0
    if m < 0 or m > 59:
        return 0
    return 1
ans = 0
#枚举第一个数字
for a in range(10):
    #枚举第二个数字
    for b in range(10):
        if a == b:
            continue
        #合法数量
        N_Y, N_D, N_H = 4, 0, 0
        A = [a, a, a, a]
        #枚举四种情况aaab、aaba、abaa、baaa
        for i in range(4):
            A[i] = b
            number = 0
            for j in A:
                number = number * 10 + j
            N_D += check_D(number)
            N_H += check_H(number)
            A[i] = a
        ans += N_Y * N_D * N_H
print(ans)

五、乘积尾零(模拟)

在这里插入图片描述

a=[5650,4542,3554,473,946,4114,3871,9073,90,4329,2758,7949,6113,5659,5245,7432,3051,4434,6704,3594,9937,
   1173,6866,3397,4759,7557,3070,2287,1453,9899,1486,5722,3135,1170,4014,5510,5120,729,2880,9019,
   2049,698,4582,4346,4427,646,9742,7340,1230,7683,5693,7015,6887,7381,4172,4341,2909,2027,7355,5649,
   6701,6645,1671,5978,2704,9926,295,3125,3878,6785,2066,4247,4800,1578,6652,4616,1113,6205,3264,2915,
   3966,5291,2904,1285,2193,1428,2265,8730,9436,7074,689,5510,8243,6114,337,4096,8199,7313,3685,211 ]
res=1
for i in a:
    res*=i
ans=0
while res%10==0:
    ans+=1
    res//=10
print(ans)

六、平方和(模拟)

在这里插入图片描述

def check(u):
    u=str(u)
    if "2" in u or "0" in u or "1" in u or "9" in u:
        return True
    return False

res=0
for i in range(1,2019+1):
    if check(i):
        res+=i*i

print(res)

DP

在这里插入图片描述

DP记忆化

在这里插入图片描述
动态规划又叫暴力的剪枝

最经典的DP问题:0/1背包

小明的背包1

在这里插入图片描述

代码1:不带空间优化的

def solve(n,C):
    for i in range(1,n+1):
        for j in range(0,C+1):
            if c[i]>j:#装不下的情况
                dp[i][j]=dp[i-1][j]
            else:
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i])
    return dp[n][C]

N=3011
dp=[[0 for i in range(N)]for j in range(N)]
w=[0]*N
c=[0]*N
n,C=map(int,input().split())
for i in range(1,n+1):
    c[i],w[i]=map(int,input().split())
print(solve(n,C))

代码2:含有空间优化的

def solve(n,C):
    now = 0
    old = 1
    for i in range(1,n+1):
        old,now = now,old #交换
        for j in range (0,C+1):
            if c[i] > j: dp[now][j] = dp[old][j]
            else: dp[now][j] = max(dp[old][j], dp[old][j-c[i]]+w[i])
    return dp[now][C]

N = 3011
dp = [[0 for i in range(N)] for j in range(2)] #注意先后
w = [0]*N
c = [0]*N
n, C = map(int, input().split())
for i in range(1, n+1):  c[i], w[i] = map(int, input().split())
print(solve(n, C))

小明背包2

在这里插入图片描述
在这里插入图片描述

N, V = map(int, input().split())
dp = [0]*(V+1)
for _ in range(N):
  w, v = map(int, input().split())
  for j in range(w, V+1):
    dp[j] = max(dp[j], dp[j-w]+v)
print(dp[-1])

装箱问题(线性DP,0/1背包)

在这里插入图片描述
在这里插入图片描述

V=int(input())
n=int(input())
dp = [0]*(V+1)
for i in range(n):
  v = int(input())
  for j in reversed(range(v, V+1)):
    dp[j] = max(dp[j], dp[j-v]+v)
print(V-dp[V])

2022

在这里插入图片描述
有两种方法,可以用暴力来做,反正是填空题,就是算C2022^10
在这里插入图片描述
在这里插入图片描述

不用滚动数组,写法一:

dp=[[[0 for _ in range(2222)]for j in range(11)]for i in range(2222)]
#初始化
for i in range(2023):
    dp[i][0][0]=1
for i in range(1,2023):
    for j in range(1,11):
        for k in range(1,2023):
            if k<i:
                dp[i][j][k]=dp[i-1][j][k]
            else:#从1~i个数里选择前j个数,他们的和为k
                dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k-i]
print(dp[2022][10][2022])

用滚动数组,写法2:

dp=[[0 for _ in range(2222)]for i in range(11)]
#初始化
dp[0][0]=1
for i in range(1,2023):
    for j in range(10,0,-1):
        for k in range(i,2023):
           dp[j][k]+=dp[j-1][k-i]
print(dp[10][2022])

过河卒

在这里插入图片描述

dp=[[0 for i in range(25)]for j in range(25)]
n,m,p,q=map(int,input().split())
n+=2
m+=2
p+=2
q+=2
s=[[0 for i in range(25)]for j in range(25)]
s[p][q]=1
s[p-2][q-1],s[p-1][q-2],s[p+1][q-2],s[p+2][q-1],s[p+2][q+1],s[p+1][q+2],s[p-1][q+2],s[p-2][q+1]=1,1,1,1,1,1,1,1
dp[2][1]=1
for i in range(2,n+1):
    for j in range(2,m+1):
        if s[i][j]==1:
            dp[i][j]=0
        else:
            dp[i][j]=dp[i-1][j]+dp[i][j-1]
print(dp[n][m])

猜你喜欢

转载自blog.csdn.net/qq_51408826/article/details/129908961