小美和大富翁

小美和大富翁

https://www.nowcoder.com/practice/e6c5d74d6d094e25be7468a21925529b

小美和大富翁

[题目链接](https://www.nowcoder.com/practice/e6c5d74d6d094e25be7468a21925529b)

思路

关键观察

每一轮小美必须使用跳跃 1、2、3、4 的四张卡牌,总共前进 个城市。因此:

  • 如果 不是 10 的倍数,则无法恰好到达第 个城市,输出
  • 总共需要 轮,每轮从当前位置前进恰好 10 格。

每轮的选择

在一轮中,小美选择四张卡牌的使用顺序(即 的一个排列),依次跳跃,途中经过 4 个城市。不同的排列会经过不同的中间城市,因此获得的金币总数也不同。

共有 种排列,每种排列对应一组经过的城市。例如排列 表示先跳 3 格、再跳 1 格、再跳 4 格、再跳 2 格,经过的城市偏移量为

贪心策略

由于金币数必须始终 ,拥有更多金币意味着更大的灵活性——当前金币越多,未来能选择的排列只会更多,不会更少。因此贪心策略是最优的:每轮在所有可行的排列中,选择金币收益最大的

具体做法:

  1. 枚举 24 种排列,对每种排列模拟 4 步跳跃。
  2. 检查每步跳跃后金币是否 (可行性检查)。
  3. 在所有可行排列中取金币收益最大值。
  4. 如果某一轮没有任何可行排列,输出

复杂度分析

  • 时间复杂度
  • 空间复杂度

代码

#include <bits/stdc++.h>
using namespace std;

int main(){
    int n;
    scanf("%d", &n);
    vector<int> a(n + 1);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);

    if(n % 10 != 0){
        printf("-1\n");
        return 0;
    }

    // 预计算 24 种排列对应的累计偏移
    int perms[24][4];
    int cnt = 0;
    int cards[] = {1, 2, 3, 4};
    do {
        int s = 0;
        for(int i = 0; i < 4; i++){
            s += cards[i];
            perms[cnt][i] = s;
        }
        cnt++;
    } while(next_permutation(cards, cards + 4));

    long long coins = 0;
    int rounds = n / 10;

    for(int r = 0; r < rounds; r++){
        int base = r * 10;
        long long best = -1;
        bool found = false;

        for(int p = 0; p < 24; p++){
            long long running = coins;
            bool valid = true;
            long long gain = 0;
            for(int i = 0; i < 4; i++){
                int city = base + perms[p][i];
                running += a[city];
                gain += a[city];
                if(running < 0){
                    valid = false;
                    break;
                }
            }
            if(valid && (!found || gain > best)){
                best = gain;
                found = true;
            }
        }

        if(!found){
            printf("-1\n");
            return 0;
        }
        coins += best;
    }

    printf("%lld\n", coins);
    return 0;
}
import java.util.*;

public class Main {
    static int[][] perms = new int[24][4];
    static int permCnt = 0;

    static void genPerms(int[] arr, int l) {
        if (l == arr.length) {
            int s = 0;
            for (int i = 0; i < 4; i++) {
                s += arr[i];
                perms[permCnt][i] = s;
            }
            permCnt++;
            return;
        }
        for (int i = l; i < arr.length; i++) {
            int tmp = arr[l]; arr[l] = arr[i]; arr[i] = tmp;
            genPerms(arr, l + 1);
            tmp = arr[l]; arr[l] = arr[i]; arr[i] = tmp;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n + 1];
        for (int i = 1; i <= n; i++) a[i] = sc.nextInt();

        if (n % 10 != 0) {
            System.out.println(-1);
            return;
        }

        genPerms(new int[]{1, 2, 3, 4}, 0);

        long coins = 0;
        int rounds = n / 10;

        for (int r = 0; r < rounds; r++) {
            int base = r * 10;
            long best = Long.MIN_VALUE;
            boolean found = false;

            for (int p = 0; p < 24; p++) {
                long running = coins;
                boolean valid = true;
                long gain = 0;
                for (int i = 0; i < 4; i++) {
                    int city = base + perms[p][i];
                    running += a[city];
                    gain += a[city];
                    if (running < 0) {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    if (!found || gain > best) {
                        best = gain;
                        found = true;
                    }
                }
            }

            if (!found) {
                System.out.println(-1);
                return;
            }
            coins += best;
        }

        System.out.println(coins);
    }
}
全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务