2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物! 他很开心的把玩,不过不小心没拿稳将数列摔坏了! 现在他手上的两个数列分别为A和B,长度分别为n和m。 小团很想再次让这两个数列变

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物! 他很开心的把玩,不过不小心没拿稳将数列摔坏了! 现在他手上的两个数列分别为A和B,长度分别为n和m。 小团很想再次让这两个数列变相关的知识,希望对你有一定的参考价值。

2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物!
他很开心的把玩,不过不小心没拿稳将数列摔坏了!
现在他手上的两个数列分别为A和B,长度分别为n和m。
小团很想再次让这两个数列变得一样。他现在能做两种操作:
操作一是将一个选定数列中的某一个数a改成数b,这会花费|b-a|的时间,
操作二是选择一个数列中某个数a,将它从数列中丢掉,花费|a|的时间。
小团想知道,他最少能以多少时间将这两个数列变得再次相同!
输入描述:
第一行两个空格隔开的正整数n和m,分别表示数列A和B的长度。
接下来一行n个整数,分别为A1 A2…An
接下来一行m个整数,分别为B1 B2…Bm
对于所有数据,1 ≤ n,m ≤ 2000, |Ai|,|Bi| ≤ 10000
输出一行一个整数,表示最少花费时间,来使得两个数列相同。
来自美团。8.20笔试。

答案2022-11-20:

尝试模型。递归。

代码用rust编写。代码如下:

use std::iter::repeat;

fn main() 
    let mut nums1 = vec![2, 1000, 2000];
    let mut nums2 = vec![999, 1, 2003];
    let ans = min_cost(&mut nums1, &mut nums2);
    println!("ans = :?", ans);


// A B
// zuo(A,B,0,0)
// A[ai.....] 对应 B[bi.....]
// 请变一样
// 返回最小代价
fn zuo(aa: &mut Vec<i32>, bb: &mut Vec<i32>, ai: i32, bi: i32) -> i32 
    if ai == aa.len() as i32 && bi == bb.len() as i32 
        return 0;
    
    if ai != aa.len() as i32 && bi == bb.len() as i32 
        return aa[ai as usize] + zuo(aa, bb, ai + 1, bi);
    
    if ai == aa.len() as i32 && bi != bb.len() as i32 
        return bb[bi as usize] + zuo(aa, bb, ai, bi + 1);
    
    // A[ai] 有数 B[bi] 有数
    // 可能性1 : 删掉A[ai]
    let p1 = aa[ai as usize] + zuo(aa, bb, ai + 1, bi);
    // 可能性2 : 删掉B[bi]
    let p2 = bb[bi as usize] + zuo(aa, bb, ai, bi + 1);
    // 可能性3 : 同时删掉
    // int p3 = A[ai] + B[bi] + zuo(A, B, ai + 1, bi + 1);
    // 可能性4 : 变!A[ai] -> B[bi] B[bi] -> A[ai]
    let p4 = if aa[ai as usize] >= bb[bi as usize] 
        aa[ai as usize] - bb[bi as usize]
     else 
        bb[ai as usize] - aa[bi as usize]
     + zuo(aa, bb, ai + 1, bi + 1);
    // 可能性5 : A[ai] == B[bi]
    return get_min(p1, get_min(p2, p4));


fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T 
    if a < b 
        a
     else 
        b
    


fn min_cost(aa: &mut Vec<i32>, bb: &mut Vec<i32>) -> i32 
    let n = aa.len() as i32;
    let m = bb.len() as i32;
    let mut dp: Vec<Vec<i32>> = repeat(repeat(-1).take((m + 1) as usize).collect())
        .take((n + 1) as usize)
        .collect();
    return change2(aa, bb, 0, 0, &mut dp);


// 暴力递归
// A[indexA....]和B[indexB....]完全一样
// 需要付出最少的代价返回
fn change(aa: &mut Vec<i32>, bb: &mut Vec<i32>, index_a: i32, index_b: i32) -> i32 
    if index_a == aa.len() as i32 && index_b == bb.len() as i32 
        return 0;
    
    if index_a == aa.len() as i32 && index_b != bb.len() as i32 
        return bb[index_b as usize] + change(aa, bb, index_a, index_b + 1);
    
    if index_a != aa.len() as i32 && index_b == bb.len() as i32 
        return aa[index_a as usize] + change(aa, bb, index_a + 1, index_b);
    
    // indexA、indexB都没到最后
    // 可能性1,丢掉A[indexA]
    let p1 = aa[index_a as usize] + change(aa, bb, index_a + 1, index_b);
    // 可能性2,丢掉B[indexB]
    let p2 = bb[index_b as usize] + change(aa, bb, index_a, index_b + 1);
    // 可能性3,同时丢掉A[indexA]、B[indexB]
    // 可能性4,把A[indexA]改成B[indexB](也是B[indexB]改成A[indexA],因为代价一样)
    // 可能性5,A[indexA]本来就是等于B[indexB]的,改的代价为0
    // 可以分析出可能性3,肯定是不如可能性4、可能性5的
    // 所以舍弃掉可能性3
    let p45 = if aa[index_a as usize] - bb[index_b as usize] > 0 
        aa[index_a as usize] - bb[index_b as usize]
     else 
        bb[index_b as usize] - aa[index_a as usize]
     + change(aa, bb, index_a + 1, index_b + 1);
    return get_min(get_min(p1, p2), p45);


// 上面的暴力递归方法改动态规划
fn change2(
    aa: &mut Vec<i32>,
    bb: &mut Vec<i32>,
    index_a: i32,
    index_b: i32,
    dp: &mut Vec<Vec<i32>>,
) -> i32 
    if index_a == aa.len() as i32 && index_b == bb.len() as i32 
        return 0;
    
    if dp[index_a as usize][index_b as usize] != -1 
        return dp[index_a as usize][index_b as usize];
    
    let mut ans = 0;
    if index_a == aa.len() as i32 && index_b != bb.len() as i32 
        ans = bb[index_b as usize] + change2(aa, bb, index_a, index_b + 1, dp);
     else if index_a != aa.len() as i32 && index_b == bb.len() as i32 
        ans = aa[index_a as usize] + change2(aa, bb, index_a + 1, index_b, dp);
     else 
        let p1 = aa[index_a as usize] + change2(aa, bb, index_a + 1, index_b, dp);
        let p2 = bb[index_b as usize] + change2(aa, bb, index_a, index_b + 1, dp);
        let p45 = if aa[index_a as usize] - bb[index_b as usize] > 0 
            aa[index_a as usize] - bb[index_b as usize]
         else 
            bb[index_b as usize] - aa[index_a as usize]
         + change2(aa, bb, index_a + 1, index_b + 1, dp);
        ans = get_min(get_min(p1, p2), p45);
    
    dp[index_a as usize][index_b as usize] = ans;
    return ans;


执行结果如下:


左神java代码

以上是关于2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物! 他很开心的把玩,不过不小心没拿稳将数列摔坏了! 现在他手上的两个数列分别为A和B,长度分别为n和m。 小团很想再次让这两个数列变的主要内容,如果未能解决你的问题,请参考以下文章

2022-04-14:小美有一个长度为n的数组, 为了使得这个数组的和尽量大,她向会魔法的小团进行求助。 小团可以选择数组中至多两个不相交的子数组, 并将区间里的数全都变为原来的10倍。 小团想知道他

CocoaChina 八岁啦!至今没收到你的祝福 ( ´◔ ‸◔`)

BZOJ 1058: [ZJOI2007]报表统计

收到了CSDN送的图书,表示感谢|对《程序员的三门课》的一表格表示疑问

bzoj 1058: [ZJOI2007]报表统计

1058. [ZJOI2007]报表统计平衡树-splay+堆