#华为机试# 华为9.1机试第一题动态规划

动态规划解决。
Javascript和python的代码,写了注释
输入输出处理省略

总体就是用dp表储存到达某个节点处两次传递的状态,[第一次的传出数量,第二次的传出数量],然后因为节点可能坏掉,那么节点i处的上一个传来节点可能是i-1或者i-2(i-2即i-1处的节点坏掉了,这样能保证没有连续的节点坏掉),取这两种情况下i处能够传递的总数量最小的那种情况记录i的状态;
然后就是理清楚如何从i-1或者i-2的状态得到i,就是下面的cal()函数完成的工作。
只需要一次遍历,最后输出n-1和n处的较小的那个即可。
let n = 3, a = 100, capability = [[50, 30], [40, 30], [20, 10]] // 测试数据
function main(n, a, capability) {
    if (n < 1) return a
    let dp = [[a, 0]] //dp[i]为[第一次传递时从i发送的数量,第二次传递时从i发送的数量],最初传来的a可以相当于是从一个最大传送量无限,最大储存量为0的节点传过来的
    dp[1] = cal(dp[0], capability[0])
    for (let i = 2; i <= n; i++) {
        let res1 = cal(dp[i - 1], capability[i - 1]) //上一个没坏,从上一个传来
        let res2 = cal(dp[i - 2], capability[i - 1]) //上一个坏掉了,从上上个传来
        dp[i] = res1[0] + res1[1] <= res2[0] + res2[1] ? res1 : res2 //状态转移,选择值最小的一种传递方案
    }
    return Math.min(dp[n][0] + dp[n][1], dp[n - 1][0] + dp[n - 1][1]) //第n个节点和第n-1个节点中传出值较小的一个,后一个相当于最后一个节点坏了
}
function cal(pre, cap) { //通过dp[i-1]或者dp[i-2]的状态来计算现在的可能值:pre为第i-1或者i-2个节点处两次传递发出的数量([第一次,第二次]);cap为i处的传输能力,即[最大发送量,最大储存量]
    let send1 = Math.min(pre[0], cap[0]) //第一次传递时从i发送的数量
    let temp = pre[0] > cap[0] ? pre[0] - cap[0] : 0  // 第一次传递时从i传出后剩的数量(因为有可能i的可发送数量大于传过来的数量,那么就剩下0)          
    let send2 = Math.min(temp + pre[1], cap[1] + pre[1], cap[0]) //第二次传递时从i发送的数量
    return [send1, send2]
}
let res = main(n, a, capability)
注:对之前的代码进行了一点修改,pre[0] 有可能小于 cap[0],如果pre[0] <=cap[0],上一次传递在i处剩下来的应该是0
let temp = pre[0] > cap[0] ? pre[0] - cap[0] : 0 
// 第一次传递时从i传出后剩的数量(因为有可能i的可发送数量大于传过来的数量,那么就剩下0)   

补充:再贴一个python的代码

n = 3
a = 100
capability = [[50, 30], [40, 30], [20, 10]] # 测试数据

# 动态规划主函数
def main(n, a, capability):
    if(n<1): 
        return a
    dp = [[a,0]] #dp[i]为[第一次传递时从i发送的数量,第二次传递时从i发送的数量],最初传来的a可以相当于是从一个最大传送量无限,最大储存量为0的节点传过来的
    dp.append(cal(dp[0],capability[0])) #通过dp[0]计算dp[1]
    for i in range(2,n+1):
        res1 = cal(dp[i-1],capability[i-1]) #上一个没坏,从上一个传来
        res2 = cal(dp[i - 2], capability[i - 1]) #上一个坏掉了,从上上个传来
        temp=res1 if(res1[0]+res1[1]<=res2[0]+res2[1]) else res2 #状态转移,选择值最小的一种传递方案
        dp.append(temp) #dp[i]
    return min(dp[n][0]+dp[n][1],dp[n-1][0]+dp[n-1][1]) #第n个节点和第n-1个节点中传出值较小的一个,后一个相当于最后一个节点坏了

#通过dp[i-1]或者dp[i-2]的状态来计算现在的可能值:pre为第i-1或者i-2个节点处两次传递发出的数量([第一次,第二次]);cap为i处的传输能力,即[最大发送量,最大储存量]
def cal(pre,cap):
    send1 = min(pre[0], cap[0]) #第一次传递时从i发送的数量
    temp = pre[0] - cap[0] if(pre[0] > cap[0]) else 0  # 第一次传递时从i传出后剩的数量(因为有可能i的可发送数量大于传过来的数量,那么就剩下0)     
    send2 = min(temp+ pre[1], cap[1] + pre[1],  cap[0]) #第二次传递时从i发送的数量
    return [send1,send2]
res=main(n, a, capability)

反正我是挂了,前两道题觉得好像做出来了,测试用例都通过,然而人迷迷糊糊,输入输出处理不熟悉,题目条件没看清,调来来跳去死活75%+5%,第一次做没经验也不知道最后一道题可以面向结果编程😂罢了罢了!!!



#华为机试##笔试题目##华为#
全部评论
做的时候完全没思路,就把无故障情况下的每个节点的流量算出来取最小。 A了65%🤣
5 回复 分享
发布于 2021-09-03 00:50
po个题目 有k个节点,每个节点的发送能力m,缓存能力为n,初始发送值为a,若节点有可能失效(失效则直接跳过节点),求经过两轮发送之后可能收到的最小值 输入: k: 5 相应m,n:50,50 20,20 40,10 30,5 10,5 初始发送值:100 输出:20 1 30,30 100 60 2 50,60 30,25 120 55
3 回复 分享
发布于 2021-09-02 19:43
vector<int>calhuawei91_1(vector<int>&pre, vector<int>&cur) {     vector<int>res;     int send1 = min(pre[0], cur[0]);//第一次传递时从i发送的数量 int tmp = (pre[0] > cur[0]) ? min(pre[0] - cur[0] , cur[1]) : 0; int send2 = min(pre[1] + tmp, cur[0]);//第二次传递时从i发送的数量 res.push_back(send1); res.push_back(send2); return res; } int huawei91_1(vector<vector<int>>&nums,int sum) {    int len = nums.size();    if (len == 0) return sum;    vector<vector<int>>dp((len + 1),vector<int>(2,0));    dp[0][0] = sum; dp[0][1] = 0;    dp[1] = calhuawei91_1(dp[0],nums[0]);    for (int i = 2; i <= len; i++)    {    vector<int> res1 = calhuawei91_1(dp[i - 1], nums[i - 1]);    vector<int> res2 = calhuawei91_1(dp[i - 2], nums[i - 1]);    dp[i] = (res1[0] + res1[1] < res2[0] + res2[1]) ? res1 : res2;    }    return min(dp[len - 1][0] + dp[len - 1][1], dp[len][0] + dp[len][1]); }
2 回复 分享
发布于 2021-09-04 17:26
你这答案不对
1 回复 分享
发布于 2021-09-03 21:39
我搞嵌入式底层驱动的也是这个题,我也很无语,不过三道题,第二题相对来说简单。
点赞 回复 分享
发布于 2021-09-02 16:30
大佬,能不能说说思路,不会java看不懂。😁
点赞 回复 分享
发布于 2021-09-02 18:54
send2这是不是应该是let send2 = Math.min(pre[0] - send1 + pre[1], cap[1] + pre[1], cap[0])  ,不然如果cap[0]比较大怎么办
点赞 回复 分享
发布于 2021-09-02 20:34
大受启发
点赞 回复 分享
发布于 2021-09-02 21:39
感觉没有全部通过的问题点是不是你把上一个节点的存储量和第二次转发量当成一样来处理了
点赞 回复 分享
发布于 2021-09-02 21:49
华为机试可以补考吗
点赞 回复 分享
发布于 2021-09-02 23:10
pre[0]-cap[0]是有可能小于0的
点赞 回复 分享
发布于 2021-09-03 17:17
我没到100也过了 说不定还有机会
点赞 回复 分享
发布于 2021-09-03 17:26
有第二题的题目吗
点赞 回复 分享
发布于 2021-09-03 22:55
遍历一遍k个节点,找出m最小的节点,再比较此节点m和n的大小关系,m大于n,结果就是m+n,m小于n,结果就是2m
点赞 回复 分享
发布于 2021-09-05 14:45
如果ABC三个节点,转移到B节点的时候为取数据量小令A节点故障,转移到C节点时候为了取数据量小,取B节点故障,这样就有连续故障了,会不会有这种情况呀
点赞 回复 分享
发布于 2021-09-05 21:05
您好,有个疑问,您这样做的话没有考虑初始节点坏了的情况吧
点赞 回复 分享
发布于 2021-09-07 15:14
请问华为考试系统里能够打断点调试么
点赞 回复 分享
发布于 2021-09-07 23:07
终于 有一个讲题的楼主了,赞!
点赞 回复 分享
发布于 2021-09-09 17:49
大佬,转移的时候选择和最小的一定最好吗,比如说[50,50]和[1,99]相比是不是有区别
点赞 回复 分享
发布于 2021-09-11 18:35
你这种做法有一个问题,对于第i个点,如果它的第i-1个节点被跳过,那么下一个点只能从第i个点传入数据因此下一个循环在temp出比较大小会出现问题。
点赞 回复 分享
发布于 2021-09-14 21:18

相关推荐

11-26 22:34
已编辑
重庆邮电大学 Java
快手 客户端开发 (n+5)k*16 公积金12
牛客895077908号:佬 什么双非硕啊
点赞 评论 收藏
分享
10-16 09:58
已编辑
门头沟学院 Java
点赞 评论 收藏
分享
Hello_WordN:咱就是说,除了生命其他都是小事,希望面试官平安,希望各位平时也多注意安全
点赞 评论 收藏
分享
评论
15
68
分享
牛客网
牛客企业服务