小美和大富翁

牛客网题目链接,第四题

小美在玩《大富翁》游戏,游戏中有 n+1 个城市排成一排,编号从 0 到 n ,第 i 个城市上有一个数字 ai,表示到达第
i 个城市可以获得 ai 枚金币。 
每一轮开始时小美会获得四张卡牌,分别可以跳跃 1、2、3、4 个城市,例如小美可以从城市1跳跃 3 个城市到达城市4。当小美使用完这 4 张卡牌后,会开启新的一轮。 


初始时,小美拥有 0 枚金币,在任意时刻,小美的金币数量都必须大于等于 0 ,
小美想知道她从第 0 个城市出发,到达第 n 个城市最多可以获得多少枚金币。
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 256M,其他语言512M
输入描述:
,第一行输入一个整数 n\ (1 <= n <= 10^5) 表示城市个数。
,第二行输入 n 个整数 a1,a2,…,an (-10^9 <= ai <= 10^9) 表示到达城市1到n可以获得的金币数量(第0个城市无法获得金币)。
输出描述:
,在一行上输出一个整数表示答案;如果无法到达第 n 个城市,则输出 -1 。
示例1
输入例子:
10
-1 2 3 4 -9 -9 -1 3 -1 -1
输出例子:
9
例子说明:
最优的方法是:
第 1 步:使用跳跃 3 的卡牌,从 0 跳到 3 ,获得 3 枚金币;
第 2 步:使用跳跃 1 的卡牌,从 3 跳到 4 ,获得 4 枚金币,共有 7 枚金币;
第 3 步:使用跳跃 4 的卡牌,从 4 跳到 8 ,获得 3 枚金币,共有 10 枚金币;
第 4 步:使用跳跃 2 的卡牌,从 8 跳到 10 ,获得 -1 枚金币,共有 9 枚金币。

20个用例,最后一个没通过,有哪位好心人,帮我看看错哪了,我看一整天了

#include<stdio.h>
#include<string.h>

void printArr(int *a, int len) {
    for (int i = 0; i < len; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");    
}

void getComb(int n, int combs[][n]) {
    int chose[n];
    int chosen[n+1];
    int index = 0;
    int i = 1;
    int index_c = 0;

    memset(chose, 0, sizeof(chose));
    memset(chosen, 0, sizeof(chosen));

    while (index >= 0)
    {
        i = chose[index] + 1;
        while (i < n+1)   // 选一个数
        {
            if (chosen[i] == 0) {
                break;
            }
            i++;
        }
        if (i == n+1) {   // 无可选,回退
            chosen[chose[index]] = 0;
            chose[index] = 0;
            index--;
            continue;
        }

        chosen[chose[index]] = 0;   // 选择新数前,释放老数
        chose[index] = i;
        chosen[i] = 1;

        index++;
        if (index == n) {
            // printArr(chose, n);
            memcpy(combs[index_c++], chose, sizeof(chose));
            chosen[i] = 0;
            index--;
        }
    }
}

long long getSocre(int *arr, int choice[4], int len, int *legal) {
    long long score = 0;
    arr--;  //初始位置不在arr[0]。。在arr[-1]
    int *end = arr + len;
    *legal = 1;
    for (int i = 0; arr != end; i++)
    {
        arr += choice[i];
        if (arr > end) {
            *legal = 0;  //代表不是正确路径,无法到达n,返回的-1无效
            return -1;
        }
        score += *arr;
    }
    return score;
}

//在任意时刻,小美的金币数量都必须大于等于 0
long long maxSocre(int arr[], int len) {
    int combiantions[4*3*2][4] = {0};
    getComb(4, combiantions);
    // printArr(combiantions[3], 4);
    long long totalSocre = 0;
    long long maxSocre = 0;
    int legal = 1;

    for (int j=0; j<(len-1)/10 + 1; j++) {
        int x = 10;
        if (len - j*10 < x) {
            x = len - j*10;
        }
        int first = 1;
        for (int i=0; i<4*3*2; i++) {
            long long score = getSocre(arr+j*10, combiantions[i], x, &legal);
            if (!legal) {
                continue;
            }
            // printf("%d  ", first);
            if (first) {
                maxSocre = score;
                first = 0;
            }
            if (maxSocre < score) {
                maxSocre = score;
            }
        }
        totalSocre += maxSocre;
        if (totalSocre < 0) {
            return -1;
        }
    }
    return totalSocre;
}

int main(int argc, char const *argv[])
{
    int n;
    scanf("%d", &n);
    int arr[n];
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
    }
    // printArr(arr, n);
    long long socre = maxSocre(arr, n);
    printf("%lld\n", socre);
    return 0;
}

### 关于牛客网小美公路算法题目的解析 #### 题目背景 根据提供的参考资料[^1],涉及到的角色“小美”通常出现在一些算法设计优化类的问题中。这类问题往往涉及数组操作、动态规划以及贪心策略的应用。 --- #### 解析:小美的加法问题 在引用[3]中提到的小美加法问题是一个典型的数组处理与最优解寻找的题目。以下是该问题的具体分析: ##### 问题描述 给定一个长度为 \( n \) 的数组 \( a \),允许将其中的一个加号替换为乘号来最大化最终的结果 \( sum \)。目标是找到通过这种变换能够得到的最大值。 ##### 思路分析 为了实现这一目标,可以通过枚举的方式逐一尝试将每一个加号替换成乘号,并计算对应的总。具体步骤如下: - 初始化最大值变量 `max_sum`。 - 对于数组中的每个位置 \( i \),分别考虑将其前后的部分相乘并加上剩余的部分。 - 更新全局最大值。 由于数据规模较大 (\( 1 \leq n \leq 10^5, 1 \leq ai \leq 10^9 \)),因此需要特别注意效率上的优化。 ##### 实现代码 以下提供了一种基于 C++ 的高效解决方案: ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; vector<long long> a(n); for (auto &x : a) cin >> x; long long totalSum = accumulate(a.begin(), a.end(), 0LL); // 计算原始总 long long maxResult = totalSum; // 初始化最大结果 for (int i = 0; i < n; ++i) { long long current = totalSum - a[i] + (a[i] * a[i]); // 替换当前项为乘积 maxResult = max(maxResult, current); // 更新最大值 } cout << maxResult << endl; return 0; } ``` 上述代码的核心在于利用预计算的总减少重复运算次数,从而降低时间复杂度至线性级别 O(n)[^3]。 --- #### 扩展讨论:平均数为 k 的最长连续子数组 另一个常见的问题是关于查找满足特定条件的子数组。例如,在引用[1]中提到了一种场景:“找出平均数等于指定数值 k 的最长连续子数组”。此类问题一般采用滑动窗口或者双指针技术加以解决。 假设我们已经知道整个序列的大小及其元素分布情况,则可通过调整左右边界逐步逼近符合条件的最佳区间范围。这种方法不仅适用于简单的均值匹配需求,还可以扩展到更复杂的约束条件下(比如限定额外权重因子等)。 --- #### 结论 综上所述,“小美”的系列挑战涵盖了多种经典计算机科学领域内的知识点,包括但不限于基础数学运算、高级数据结构应用以及高效的搜索技巧等方面的内容。希望以上解答能为你带来启发! --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值