题目链接:https://ac.nowcoder.com/acm/problem/212985

到主站看:https://blog.csdn.net/weixin_43346722/article/details/109140863

题目

牛牛最近在玩一种叫做跳跳棋的游戏,棋盘可以看成是一个一维的线性数组,编号从
一开始牛牛的棋子位于第 个格子,游戏的最终目的是将棋子移动到第 个格子。
棋盘 的每个格子都有一个“弹力系数”的权值
当棋子位于第 个格子时,它的下一步可以移动到 范围内的任意一个格子。
举例来说,假设第 个格子的弹力系数为 ,那么牛牛下一步可以移动到第 格中的任意一格。
现在给定 每格的弹力系数

牛牛发现,好像有时由于棋盘的 设置不合理,导致游戏无法通关。
所以牛牛准备施展他神奇的魔法,他每次施展魔法都可以使得一个格子的弹力系数 ,他可以施展若干次魔法操作不同的格子,但是要求他不能够重复对一个格子施展魔法。
牛牛想要知道,为了使跳跳棋通关,他最少施展多少次魔法,并且他应该操作哪些格子。
请输出牛牛的最小操作次数,以及施展魔法的操作序列,操作序列的第i个数表示该次施展魔法的格子编号,由于答案不唯一,所以请你输出一个最小字典序的答案。

最小字典序指:在保证第 个数字尽可能小的前提下,保证第 个数字尽可能的小,然后在此前提下保证第 个数字尽可能的小....以此类推。

输入

第一行输入一个正整数 表示跳跳棋的格子数目。
接下来输入一行 个非负整数 表示跳跳棋前 个格子的弹力系数。

输出

首先输出一个非负整数 ,表示少施展魔法的次数。
如果 不为 ,则再输出一行 个整数表示需要施展魔法的格子编号,请给出一个最小字典序的答案。

样例输入1

12
5 4 3 3 2 1 0 0 0 1 0 0

样例输出1

5
4 8 9 10 12

样例解释1

除了 "4 8 9 10 12" 这个操作的答案序列以外, "5 8 9 10 12"、"6 8 9 10 12" 也同样是最小操作数下的答案。
但是 "4 8 9 10 12" 这个答案是字典序最小的,故输出 "4 8 9 10 12"。

样例输入2

8
0 1 0 1 0 1 0 1

样例输出2

4
1 2 4 6

样例输入3

5
0 0 0 0 0

样例输出3

5
1 2 3 4 5

样例解释3

本样例可以说明,不存在无解的情况,因为你至少可以令所有 全都 +1。

样例输入4

5
1 1 1 1 1

样例输出4

0

数据范围

对于 的测试数据,保证
对于 的测试数据,保证
对于 的测试数据,保证

思路

这道题是一道贪心。

我们可以看出,往后走是没有任何的必要的。
因为你走是可以走到 中的任意一个点,那你走回去,再走回来,其实不如你直接往前走。

那这道题就可以很愉快的用贪心解决了,在用魔法之前竟可能的走到更前面,然后在跳最后一次的地方用一次魔法。

这时候可能会有人问:为什么这样一定可以呢?
因为它无论在什么地方使用魔法,都只能在原来的基础上多走一步,那肯定就是先找到能走到最远地方的最后一点,然后再那个地方用魔法。

然后我们只要在走的时候记录一下在那些地方用了魔法,在到终点之后输出出来就可以了。

题目要求要字典序最小,那我们不往后走,而且如果有两个地方都可以跳到最远点,就选前面的那个。

考试时

之前好像有接触过类似的题目,于是很快就看出来。
寻思了一会之后,就把它码出来了。
得分:
图片说明

代码

#include<cstdio>

using namespace std;

int n, a[100001], maxn = 1, maxx = 1, num[100001];

void write() {
    printf("%d\n", num[0]);
    for (int i = 1; i <= num[0]; i++) printf("%d ", num[i]);
}

int main() {
    scanf("%d", &n);

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

        if (a[i]) {
            if (i + a[i] > maxn) {//贪心,在不魔法的情况下能走多远走多远 
                maxn = i + a[i];
                maxx = i;

                if (maxn > n) write();//可以走到终点了
            }
        }
        else if (i == maxn) {//已经尽可能的走的更远了,一定要用魔法
            num[++num[0]] = maxx;
            maxn++;
            maxx = maxn;

            if (maxn > n) write();//用完魔法就到终点了
        }
    }

    return 0;
}