[蓝桥杯 2024 省 A] 训练士兵

题目 

链接:P10387 [蓝桥杯 2024 省 A] 训练士兵 - 洛谷

注意细节:第一行是n和S,然后是“接下来的n行”,这n行士兵,分别是金币数和次数 

思路

 发现说,一般来说是团购价格<单独训练价格,是尽可能先团购,再单独训练

贪心+排序的思路,先贪心,找到最大团购次数,然后剩下的再单独训练

代码

n,S=map(int,input().split())
lst=[]
for i in range(n):
    p,c=map(int,input().split())
    lst.append([p,c])
lst.sort(key=lambda x:x[1]) # 默认升序
num=lst[0][1]
pri=num*S # 团购次数*价钱
for j in range(1,n):
     pri+=lst[j][0]*(lst[j][1]-num)
print(pri)

反思

  1. 看懂题目
    • 组团训练 VS 单独训练
    • 输入格式。第一行为n和S,n为成员数,S为组团训练价钱;接下来n行是p和c,即单次价钱和训练次数
  2. 理清思路
    • 当人数充足时,团体训练更为划算,所以我们要优先团体训练,剩下再单独训练
  3. 代码如何输入数据
    • `a,b=map(int,input().split())`-->表示输入时为两个数,用空格间隔{map表示映射,输入的为int类型,input输入,split分割,默认空格分割},分别赋值给a和b
    • 注意看看清楚,一定是先读取n和S,再根据n,决定后面需要输入多少次
  4. 掌握排序
    • 我输入p和c时,使用多次循环,每次循环中为[p,c],再使用append加入列表
    • 在分析是我们知道,要确定最大团购数->最小训练数,此时我们要对每个列表的第二个元素进行排序,所以要确定排序规则key,`lst.sort(key=lambda x:x[1])`,默认是升序
### 训练士兵问题分析 此问题是关于如何通过最优策略来最小化总成本,使所有士兵都能达到顶尖战士的要求。具体而言,可以通过单独训练和团购训练两种方式完成目标。 #### 单独训练与团购训练的选择逻辑 对于每一名士兵 \(i\) 来说,其单独训练的总费用为 \(p_i \times c_i\) 枚金币[^1]。然而,如果采用团购训练,则每次仅需支付固定金额 \(S\) 枚金币即可让多名士兵共同参与一次训练。因此,在实际操作中,应优先考虑团购训练的可能性,以减少整体开销。 #### 动态规划解决方法 定义状态转移方程如下: 设 \(dp[j]\) 表示当前已满足前若干名士兵成为顶尖战士所需的最低花费,并假设此时剩余未完全覆盖次数总计恰好等于\(j\)[^2]。初始条件设定为当没有任何额外需求时(\(j=0\))对应零消耗;其他情况初始化无穷大表示不可达状态。 接着遍历每一位士兵及其可能贡献给团购方案中的部分或全部训练机会数k (其中 k 范围从 max(0, j-c[i]) 到 min(j ,c[i])) ,更新 dp 数组值直到处理完最后一位为止: \[ dp'[j-k+\min(c[i],k)] = \min(dp'[j-k+\min(c[i],k)], dp[j]+cost)\] 最终答案即为 dp[0]. 以下是基于上述思路实现的一个 Python 解决方案: ```python def minimal_cost(n, p, c, S): import sys INF = sys.maxsize total_c = sum(c) # Initialize DP array with infinity values. dp_prev = [INF]*(total_c + 1) dp_curr = [INF]*(total_c + 1) dp_prev[0] = 0 for i in range(n): temp_dp = [INF]*(total_c + 1) for j in range(total_c + 1): if dp_prev[j] != INF: cost_single = p[i]*max((c[i]-j),0)+S*(int(max((j+c[i])/len(p)))) new_j = min(total_c,j+c[i]) temp_dp[new_j]=min(temp_dp[new_j],dp_prev[j]+cost_single) dp_prev=temp_dp result=min([val for idx,val in enumerate(dp_prev)]) return result # Example usage of the function based on provided data structure from references. if __name__ == "__main__": n = int(input()) p = list(map(int,input().split())) c = list(map(int,input().split())) S = int(input()) answer = minimal_cost(n,p,c,S) print(answer) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值