POJ1012 约瑟夫问题

/* 功能Function Description:     约瑟夫环+枚举  POJ-1012
   开发环境Environment:          DEV C++ 4.9.9.1
   技术特点Technique:
   版本Version:
   作者Author:                   可笑痴狂	
   日期Date:                     20120731
   备注Notes:
   大致题意:
		有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k)
		现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去。
		问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉?
 
    PS:当前一轮第m个人死去后,下一轮的编号为1的人 为 前一轮编号为m+1的人
	     前一轮恰好是最后一个人死掉,则下一轮循环回到开头那个人报“1”
*/

/*
//代码一:用顺序表实现---枚举( 超时TLE)
#include<stdio.h>
#include<malloc.h>

int main()
{
	int *base;
	int i,k,j,t,flag,sum;
	while(scanf("%d",&k),k)
	{
		base=(int *)malloc((2*k)*sizeof(int));
		flag=1;
		for(i=k+1;flag;++i)            //从k+1开始向后枚举
		{
			sum=k*2;                  //sum 存储总人数
			for(t=0;t<2*k;++t)        //每次都要重新初始化
				base[t]=t+1;
			for(j=(i-1)%sum;;)   //j存储每次去除的人的下标
			{
				if(base[j]<=k)
					break;
				for(t=j+1;t<sum;++t)   //删除该节点---后边元素依此前移
					base[t-1]=base[t];
				--sum;
				if(sum==k)
				{
					flag=0;
					printf("%d\n",i);
					break;
				}
				j=(j+i-1)%sum;
			}
		}
		free(base);
	}
	return 0;
}
*/

/*
//代码二:把代码一中打表(AC)
#include<stdio.h>
int main()
{
	int k;
	int Joseph[14]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
	while(scanf("%d",&k),k)
		printf("%d\n",Joseph[k]);
	return 0;
}
*/

//代码三:用数学方法递推
//出处:http://blog.csdn.net/lyy289065406/article/details/6648444
/*
递推公式为:
	ans[i];  //第i轮杀掉 对应当前轮的编号为ans[i]的人
	ans[0]=0;
	ans[i]=(ans[i-1]+m-1)%(n-i+1);   (i>1  ,  总人数n=2k 则n-i为第i轮剩余的人数)
*/
//Memory Time
//184K   250MS 

#include<iostream>
using namespace std;

int main(void)
{
	int Joseph[14]={0};  //打表,保存各个k值对应的m值
	int k;
	while(cin>>k)
	{
		if(!k)
			break;

		if(Joseph[k])
		{
			cout<<Joseph[k]<<endl;
			continue;
		}

		int n=2*k;  //总人数
		int ans[30]={0};  //第i轮杀掉 对应当前轮的编号为ans[i]的人
		                  //PS:每一轮都以报数为“1”的人开始重新编号

		int m=1;    //所求的最少的报数
		for(int i=1;i<=k;i++)  //轮数
		{
			ans[i]=(ans[i-1]+m-1)%(n-i+1);   //n-i为剩余的人数
			if(ans[i]<k)  //把好人杀掉了,m值不是所求
			{
				i=0;
				m++;  //枚举m值
			}
		}
		Joseph[k]=m;
		cout<<m<<endl;
	}
	return 0;
}
功不成,身已退
原文地址:https://www.cnblogs.com/dongsheng/p/2617689.html