现在的位置: 首页 > 综合 > 正文

hdu — 1443 Joseph

2014年03月15日 ⁄ 综合 ⁄ 共 1639字 ⁄ 字号 评论关闭

     约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”)
    据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
   

   在hdu中,这道题要先杀掉后排才能杀掉前排,且杀掉一个人后,重新回环,即题目为杀掉后排之前不得杀掉前排,于是如下:
   1.将死之人为 die = m % i == 0 ?i :m % i;(i是剩余的人数)
   2.不可杀的范围:!(a[die] =< k && a[die] >= 1)不为前k个人(前面给数组赋了初值)

   3.移位

借助a[ 0 ]进行移位,先将最后一位移给a[ 0 ],再将数组整体后移移位,直到a [ 0 ] ==  b ; (b == a[die]).


   代码如下 

#include<stdio.h>
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	int a[25],k,m,die,kill;
	while(scanf("%d",&k) != EOF)
	{
		for(m = k + 1;;m++)
		{
			//给数组赋初值
			for(int i = 1; i <= 2*k; i++)
				a[i] = i;
			kill = 0; //已杀人数
			for(int i = 2 * k;;i--)
			{
				die = m % i == 0 ? i : m % i;
				if(!(a[die] >= 1 && a[die] <= k)) //条件判断
				{
					int b = a[die];
					kill++;
					a[0] = a[i]; 
					while(a[0] != b)  //移位
					{
						for(int j = i; j > 0; j--)
							a[j] = a[j - 1];
						a[0] = a[i];
					}
				}
				else  break;
			}
			if(kill == k) { printf("%d,",m); break;}		
		}

	}
	return 0;
}

   这时打出的代码在k = 14 时候,将近需要11s,这严重超时啊有木有~~~~~

   这时考虑到约瑟夫问题数据少,所以可以用打表法来过题,所谓打表法,先写代码将数据打出,然后初始化于数组中,这里推荐使用输入流和输出流,我使用了freopen(“input.txt”,“r”,stdin);

freopen(“output.txt”,“w”,stdout);将这两代码,写于main函数入口处,之后的scanf只会从文件input.txt读入数据,所以要自己新建,一般建于与cpp相同的目录下,也可以建于其它地方,但要写绝对路径或相对路径(默认是与cpp相同的目录),例如:freopen(“D://hdu/joseph/input.txt”,"r",stdin);你的printf将把数据写于output.txt中(不必自己新建),这样,你就可以简单的将数据复制给数组打表了。

    打表代码:

#include<stdio.h>
int a[14] = {2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,13482720};
int main()
{
    int b;
    while(scanf("%d",&b) == 1 && b != 0)
    {
        printf("%d\n",a[b-1]);
    }
    return 0;
}

抱歉!评论已关闭.