【每日一题】农场主牛牛

发布时间 2023-06-28 00:21:16作者: 橘友纪

 

思路
非常简单的题目(却花了我一天时间)。大体思路是找到无人机施肥规律:每次遍历n-1行,直到末尾之前停下——然后到末尾调转方向。依题意m为肥料质量,n为农田行数。设全体农田为数列answer,设完整施肥completed_times轮(完整施肥即本轮n-1行农田全部均完成施肥),剩余肥料可使用在remain行上,不难证

 completed_times = m / (n - 1)
 remain = m % (n - 1)

若remain为0,则肥料能够完整的覆盖completed_times次农田而不会有不完整的轮数出现。此时不难发现有如下规律:

当completed_times为奇数时,最左侧农田施肥量总比最右侧多1,且总比completed_times的一半多1;
当completed_times为偶数时,最左侧农田施肥量总等于最右侧,且总为completed_times的一半。
以上为最后一轮剩余肥料质量正好可用于一轮的情况。在这个基础上只需要强行遍历剩下的部分即可。

而总结规律会发现,当 completed_times是奇数或0时,最后一轮的行进方向是从左向右;是偶数时为从右向左。而一轮的开始总在首行或尾行,由此便知道最后一轮施肥的开始位置和行进方向。接着便是交给计算机完成的机械遍历工作了。

代码

pub fn FarmerNN(&self, n: i32, m: i64) -> Vec<i64> {
        // write code here
        let mut answer: Vec<i64> = vec![];
 
        // 已完成的圈数
        let completed_times = m / (n - 1) as i64; 
        // 剩余的肥料千克数
        let mut remain = m % (n - 1) as i64;
        // 如果已完成圈数是奇数,则当前从左向右
        // 否则当前从右向左
        let mut direct: i8 = if completed_times % 2 == 0 || completed_times == 0 { -1 } else { 1 };
        // 填充已完成部分
        for i in 0..n as usize {
            answer.push(0);
            if i == 0 {
                answer[i] = if direct == 1 { (completed_times >> 1) + 1 } else { completed_times >> 1 };
            } else if i == (n - 1) as usize {
                answer[i] = completed_times >> 1;
            } else {
                answer[i] = completed_times;
            }
        }
 
        let mut now_i: usize = if direct == 1 { (n - 1) as usize } else { 0 as usize };
        while remain > 0 {
            answer[now_i] += 1;
            remain -= 1;
            if direct == 1 && now_i + 1 > (n - 1) as usize {
                direct *= -1;
            } else if direct == -1 && now_i == 0 {
                direct *= -1;
            }
            // now_i = (now_i as i8 + direct) as usize;
            if direct == 1 {
                now_i += 1;
            } else {
                now_i -= 1;
            }
        }
 
        answer
    }