P2069 松鼠吃果子

文章描述了一道编程题,题目涉及一只松鼠按特定规则跳跃吃果子的过程。给定果子数量n和跳跃次数m,要求找出松鼠吃的第m个果子的编号。解题方法包括使用数组和链表实现,考虑果子被吃掉后的影响及当松鼠跳出序列时回到起点的情况。
摘要由CSDN通过智能技术生成

题目描述

 

输入输出样例

输入 #1

10 
4

输出 #1

9

说明/提示

注:吃掉的果子依次为 3,8,5(回到下面重做第 3 跳),9(回到下面重做第 4 跳)。


写着感觉好别扭

感觉和字符串没啥关系。。

然后洛谷那里的这个有问题:

第三跳吃的是编号5的果子


 

思路:

我的想法是定义一个int数组,初始化为1,表示有果子,0表示没果子。

循环m次,每次循环先计算每次跳多远,即代码中的jump;

然后判断从当前位置pos加上跳的距离jump是否跳得超过了n,超过了就回到初始位置,也就是pos=1;

最重要的来了,我们不能一下跳jump那么远,得一步一步跳,遇到被吃掉的果子,也就是int数组为0,那么这一步不算,重新跳。

代码1:(数组)

#include<iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;

    int array[300];
    fill(array, array + n, 1);
    int cnt = 1, pos = 1, jump;
    while (m--) {
        jump = (cnt*cnt*cnt)%5 + 1;
        cnt++;
        if (pos + jump > n) {
            pos = 1;
        }
        int i;
        for (i = pos+1;1; i++) {//不能一下跳jump那么远,得一步一步跳
            if (array[i]) {
                jump--;
            }
            if (!jump) {
                break;
            }
        }
        array[i] = 0;
        pos = i + 1;
    }

    cout << pos-1 << endl;
    return 0;
}

代码2:(链表)

因为这道题涉及到了结点的删除,如果数据量大的话,使用数组会花费很多时间在数据的移动上,所以用的链表。

但是这道题不能用循环链表,因为如果松鼠会跳出这串果子的最前面,它吃不到任何果子时,要回到第一个位置,重新跳;如果是循环链表的话,会计算当前位置到末尾的位置,算到跳跃的步数里。

#include<iostream>
using namespace std;

struct List {
    int data;
    List* next;
};

int main()
{
    int n, m;
    cin >> n >> m;
    List * rear=NULL;

    List* head = (List*)malloc(sizeof(List));
    head->data = -1;
    head->next = NULL;

    for (int i = n; i >= 1; i--) {
        List* newNode = (List*)malloc(sizeof(List));
        newNode->data = i;
        newNode->next = NULL;

        newNode->next = head->next;
        head->next = newNode;
    }

    int jump, cnt;
    List* p = head->next, *pre = NULL;
    for (int i = 1; i <= m; i++) {
        jump = (i * i * i) % 5 + 1;
        cnt = jump;

        while (cnt--) {
            if (p->next == NULL) {
                p = head->next;
                cnt = jump;
                continue;
            }
            pre = p;
            p = p->next;
        }

        if (i != m) {
            pre->next = p->next;
            p = p->next;
        }

    }

    cout << p->data << endl;
    return 0;
}

代码3:(数组模拟链表)

用数组fa[]和数组son[]实现模拟双向链表

对于skip函数里面的for循环,它退出只有两种情况,s为0或者pos为0,当s为0时表示没跳到末尾,正常进行删除;如果pos为0,说明跳到了末尾,这时候需要返回开始的地方重新跳。

#include<iostream>
#define MAX 300
using namespace std;
int fa[MAX], son[MAX], n, m, pos = 1;

void skip(int s) {
    for (; s && pos; s--, pos = fa[pos]);
}

void del(int x) {
    pos = fa[x];
    fa[son[x]] = fa[x];
    son[fa[x]] = son[x];
    fa[x] = son[x] = -1;
}

int main()
{
    cin >> n >> m;
    fa[1] = 2;
    son[n] = n - 1;

    for (int i = 2; i < n; i++) {
        fa[i] = i + 1;
        son[i] = i - 1;
    }

    for (int i = 1; i <= m; i++) {
        int s = (i * i * i) % 5 + 1;
        skip(s);

        if (!pos) {
            pos = 1;
            skip(s);
        }
        if (i == m) {
            cout << pos << endl;
            return 0;
        }
        del(pos);
    }
    return 0;
}

代码4:(vector容器实现动态数组)

其实就是用数组,然后删除,移动,不过vector数组的erase方法帮我们实现了移动

#include<iostream>
#include<vector>
#define MAX 300
using namespace std;

int main()
{
    int m, n;
    cin >> n >> m;
    
    vector<int> v;
    for (int i = 1; i <= n; i++) {
        v.push_back(i);
    }

    int jump, pos = 1;
    for (int i = 1; i <= m; i++) {
        jump = (i * i * i) % 5 + 1;
        pos += jump;

        if (pos > v.size()) {
            pos = 1;
            pos += jump;
        }

        if (i == m) {
            cout << v[pos-1] << endl;
        }

        v.erase(v.begin()+pos-1);
    }

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值