Py小郑 2022-03-29 09:11 采纳率: 96.6%
浏览 147
已结题

有关蓝桥杯砝码称重 DP问题

我已经思考过很久了,就是不知道问题出在哪?

img

n=int(input())

v=list(map(int,input().split()))
v.insert(0,0)
M=sum(v)
#0是称不出来的,称重范围(0,M]
dp=[[0]*(2*M) for i in range(n+1)]#前i个物品能否组合出j的重量
#设置2M为了数组下标防止越界

for i in range(1,n+1):
    for j in range(1,M+1):
        dp[i][j]=dp[i-1][j]
        if v[i]==j:
            dp[i][j]=1
        if dp[i][j]==1:
            continue
        if j>v[i]:
            dp[i][j]=dp[i-1][j-v[i]]
        elif j<v[i]:
            dp[i][j]=max(dp[i-1][v[i]+j],dp[i-1][v[i]-j])
        else:
            pass
ans=0
for i in dp[-1]:
    if i==1:
        ans+=1
print(ans)


我的思路:先在v数组添加一个(0,0)代表第0个砝码的重量是0,方便后面下标书写。
然后dp[i][j]代表前i个物品能否称重出j的重量,可以为1,不可以为0
dp[i][j]至少等于dp[i][j-1],第一步。如果第i个物品已经等于j,dp[i][j]=1,第二步。
经过第一部和第二步,如果dp[i][j]已经为1,那么就不需要在做下去了,进入下一次循环dp[i][j+1]
否则,即dp[i][j]=0,如果j过大,只需要考虑前i-1个物品能否凑出j-v[i]
如果j过小,我们只需要考虑前i-1个物品能否凑出v[i]+j,或v[i]-j,可是程序只对了20%,问题错在哪呢?
下面是正确的代码:

    n=int(input())
    #dp[i][j]表示加上第i个砝码,j的重量是否可以被称出,可以被称出则j=1,不可以则j=0
    a=list(map(int,input().split()))
    sum=0 #sum是j的范围
    for i in a:
        sum+=i
    dp=[[0]*2*sum for i in range(n+1)]      #*列   for in 行
    result=0
    for p in range(1,n+1):
        for q in range(1,sum+1):
            dp[p][q]=dp[p-1][q]
            if dp[p][q] == 0:   #只看前p-1个无法称量的
                if a[p-1]==q:
                    dp[p][q]=1
                if dp[p-1][a[p-1]+q]:  #放在不同侧(即相减)  返过去判断就要相加
                    dp[p][q]=1
                if dp[p-1][abs(a[p-1]-q)]:
                    dp[p][q]=1
    for i in dp[n]:
        if i==1:
            result+=1
    print(result)


请求指导!

  • 写回答

2条回答 默认 最新

查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月13日
  • 已采纳回答 4月5日
  • 创建了问题 3月29日

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作