约瑟夫环的变形

问题描述:

输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m。从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止。如果计数到达数列尾段,则返回数列首位置继续计数。请编程实现上述计数过程,同时输出数值出列的顺序。

比如:输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置)

第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4,从数值4所在位置从新开始计数

第二轮计数出列数字为3,计数值更新m=3,出列后数列为1,4,从数值1所在位置开始计数

第三轮计数出列数字为1,计数值更新m=1,出列后数列为4,从数值4所在位置开始计数

最后一轮计数出列数字为4,计数过程完成。

输出数值出列顺序为:2,3,1,4。

要求实现函数:

void array_iterate(int len, int input_array[], int m, int output_array[])

输入:

int len:输入数列的长度;

int intput_array[]:输入的初始数列

int m:初始计数值

输出:

int output_array[]:输出的数值出列顺序

返回值:

C代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

typedef struct _node
{
	struct _node* prev;
	struct _node* next;
	int number;
}node,*linklist;

linklist create(int len, int input_array[]);
void array_iterate(int len, int input_array[], int m, int output_array[]);
void display_array(int len, int array[]);

int main()
{
	int input_array[] = {12,1,34,56,28,9,17};
	int len = sizeof(input_array)/sizeof(input_array[0]);
	int *output_array = (int *)malloc(len*sizeof(int));
	int m;
	printf("please input m:");
	scanf("%d",&m);
	printf("the original sequences are:");
	display_array(len, input_array);
	array_iterate(len, input_array, m, output_array);
	return 0;
}
linklist create(int len, int input_array[])
{
	linklist head = (linklist)malloc(sizeof(node));
	node *tail;
	int i=0;
	head->prev = head;
	head->next = head;
	head->number = input_array[i];
	tail = head;
	for(i=1;i<len;i++)
	{
		node *p = (node*)malloc(sizeof(node));
		p->number = input_array[i];
		p->next = tail->next;
		p->prev = tail;
		tail->next = p;
		tail = p;
		head->prev = tail;
	}
	return head;
}

void array_iterate(int len, int input_array[], int m, int output_array[])
{
	linklist head;
	head = create(len, input_array);

	int i,j;
	node *p,*q;
	p = head;
	for(i=0; i<len; i++)
	{
		if(m == 1)
		{
			q = p->next;
			p->prev->next = q;
			q->prev = p->prev;
			m = p->number;
			output_array[i] = m;
			free(p);
			p = q;
		}
		else
		{
			for(j=1; j<m-1; j++)
				p = p->next;
			q = p->next;
			p->next = q->next;
			q->next->prev = p;
			m = q->number;
			output_array[i] = m;
			free(q);
			p = p->next;
		}
	}
	printf("the sequences of leaving the list are:");
	display_array(len, output_array);
}
void display_array(int len, int array[])
{
	int i;
	for(i=0; i<len; i++)
		printf("%d ",array[i]);
	printf("\n");
}

关于以上代码,需要注意的是m的值是否等于1,为了方便处理m=1的情况,使用了双向的循环链表。

注:网上很多有关约瑟夫的代码都没有考虑到m=1的情况。

几组测试用例的结果如下:

约瑟夫环的变形

时间: 2024-10-23 05:10:20

约瑟夫环的变形的相关文章

UVALive 3882--And Then There Was One+约瑟夫环问题变形

题目链接:点击进入 题目意思大概和约瑟夫环问题差不多,唯一的不同点在于起点改成了m:刚开始的时候我想直接链表模拟算了,但是后面一看,数据太大,就改用公式做了.约瑟夫环的公式是:f(n)=(f(n-1)+k)%n ,对于这个题起点为m,所以答案就会变成ans=(f(n)+m-k+1)%n; ans有可能小于0,此时我们要给他加上一个n,ans+=n. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

【约瑟夫环变形】UVa 1394 - And Then There Was One

首先看到这题脑子里立刻跳出链表..后来继续看如家的分析说,链表法时间复杂度为O(n*k),肯定会TLE,自己才意识到果然自个儿又头脑简单了 T^T. 看如家的分析没怎么看懂,后来发现这篇自己理解起来更容易(...)共享一下~http://blog.csdn.net/chenguolinblog/article/details/8873444 问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数.求胜利者的编号. 编号0~(n-1)是有意义的,因为要

Poj 3517 And Then There Was One(约瑟夫环变形)

简单说一下约瑟夫环:约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 想要求出最后剩下的那个人的在初始的时候的编号的话. f[1]=0; f[i]=(f[i-1]+m)%i;  (i>1) 可以推出剩下i个人内叫到m的时候的编号.注意这是逆推.推到最后初始的时候的情况 #include<stdio.h>

HDU 5643 King&#39;s Game | 约瑟夫环变形

经典约瑟夫环 1 int f[N] ={ 0 }; 2 for(int i=2; i<=n; i++) 3 { 4 f[i] = (f[i-1] + k) % i; 5 } 变形:k是变化的 #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <stdlib.h> #include <queue> #in

poj 1012 &amp; hdu 1443 Joseph(约瑟夫环变形)

题目链接: POJ  1012: http://poj.org/problem?id=1012 HDU 1443: http://acm.hdu.edu.cn/showproblem.php?pid=1443 约瑟夫环(百度百科): http://baike.baidu.com/view/717633.htm?fr=aladdin Description The Joseph's problem is notoriously known. For those who are not famili

POJ 3517 And Then There Was One (约瑟夫环问题)

经典的约瑟夫环问题嘛.有点小小的变形而已.给你N个人围成一个环(编号1~N),从第M个人开始,每隔K个人报一次数,报数的人离开该环. 求最后剩下的人的编号. 约瑟夫问题的数学递推解法: (1)第一个被删除的数为 (m - 1) % n. (2)假设第二轮的开始数字为k,那么这n - 1个数构成的约瑟夫环为k, k + 1, k + 2, k +3, .....,k - 3, k - 2.做一个简单的映射. k         ----->  0 k+1    ------> 1 k+2    

约瑟夫环以及其变种集合

最近在CF上补题,补到了一道关于约瑟夫环的题目(听都没听过,原谅我太菜) 就去好好学了一下,不过一般的题目应该是不会让你模拟过的,所以这次就做了一个约瑟夫环公式法变形的集合. 关于约瑟夫环的基础讲解,我个人认为最好的就是这篇了. 首先是最原始的约瑟夫环的题目: https://vjudge.net/problem/51Nod-1073(小数据规模) #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with

一个不简洁的约瑟夫环解法

约瑟夫环类似模型:已知有n个人,每次间隔k个人剔除一个,求最后一个剩余的. 此解法为变种,k最初为k-2,之后每次都加1. 例:n=5,k=3.从1开始,第一次间隔k-2=1,将3剔除,第二次间隔k-1=2,将1剔除.依此类推,直至剩余最后一个元素. 核心思路:将原列表复制多份横向展开,每次根据间隔获取被剔除的元素,同时将此元素存入一个剔除列表中.若被剔除元素不存在于剔除列表,则将其加入,若已存在,则顺势后移至从未加入剔除列表的元素,并将其加入.如此重复n-1次.面试遇到的题,当时只写了思路,没