zoukankan      html  css  js  c++  java
  • 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;
    }
    
    功不成,身已退
  • 相关阅读:
    centos 安装 谷歌BBR
    centos上mailx通过465端口发送邮件
    centos 6的LAMP一键安装包(可选择/升级版本)
    Linux 一键安装最新内核并开启 BBR 脚本
    CentOS 7安装Xfce和VNC
    重构手法之简化函数调用【4】
    重构手法之简化函数调用【3】
    重构手法之简化函数调用【2】
    重构手法之简化函数调用【1】
    重构手法之简化条件表达式【4】
  • 原文地址:https://www.cnblogs.com/dongsheng/p/2617689.html
Copyright © 2011-2022 走看看