题目描述
输入输出样例
输入 #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;
}