一、Description

The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last
remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4,
6, 2, 3 and 1 will be saved.



Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.

二、问题分析

        刚开始的时候没看懂英文,找了个翻译:约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。假定在圈子里前K个为好人,后K个为坏人,你的任务是确定这样的最少M,使得所有的坏人在第一个好人之前被杀掉。这道题感觉不容易,看了很多提示才有点感觉。

       开始的时候总想着用什么数据结构实现这个环,什么链表,栈之类的。又总是琢磨从0开始还是从1开始,傻逼逼地在那比对公式的输出结果数字。后来发现完全没有必要,因为好人与坏人总是分在两个K内的。好人在小的那一部分,坏人在较大的那部分。所以只要下个要杀的人>k就可以继续循环。这里比较坑爹的是,测试数据里面有相同的K,如果不用记忆化存储的话,可能会超时。所以,这里好多人就干脆打表了。

       什么是打表呢?如果第一个测试用例让你求第100个,那么你可以将前100个数据在自己电脑里算好再存起来,这样如果题目再问到小于100的情况,就我们就可以直接输出了,相当于查表输出,时间耗时就自然少的多了。如果第二个测试用例让我们求第200个,那么我们就从第101个算起,算出的结果继续存起来,以备下一次的实用,如此类推,这个存起来的过程就叫做打表。(打表法貌似被不少人鄙视)

      不用打表其实也是可以过的,前辈们总结了三点,再次小弟引用一下:

            1.要kill的人的位置公式p=(p+m-1)%rest+1

            2.kill的位置<k就break,此时剩下的人rest等于k就成功

            3.m不要递增,如6个人,m取1,2,3第一次就杀了好人了,没意义。m是k+1的整数倍或者k+1的整数倍加1,这样会提高不少。
import java.util.Scanner;

public class Poj1012_Joseph {

	public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
int res[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//1~14,0位置不存放
int k=0;
while((k = cin.nextInt()) != 0){
int m=0;
if(res[k]==0){
while(true){
if(m/k==0)
m += k+1;
else
m ++;
int rest=2 * k;
int pos=0;
while(true){
pos=(pos+m-1)%rest+1; //位置公式
if(pos>k){
pos--;
rest--;
}else{
break;
}
}
if(rest==k){
res[k]=m;
break;
}
}
}
System.out.println(res[k]);
}
}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Poj1012_Joseph的更多相关文章

随机推荐

  1. PAT 1055. 集体照 (25)

    拍集体照时队形很重要,这里对给定的N个人K排的队形设计排队规则如下: 每排人数为N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排任何人矮: 每排中最高者站中间(中间位置为m ...

  2. JVM相关的几个基本概念

    1.虚拟机是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统 2.常见的虚拟机有VMWare,Visual Box,JVM等 VMWare或者Visual Box模拟的 ...

  3. Linux根目录下重要文件夹

    bin存放系统命令的目录,普通用户和超级用户都可以执行,不过放在这里的命令在单用户模式下也可以执行 sbin保存和系统环境设置相关的命令,只有超级用户可以使用这些命令进行系统环境的设置,但有些命令可以 ...

  4. Linux内核设计基础(九)之进程管理和调度

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/BlueCloudMatrix/article/details/30799225 在Linux中进程用 ...

  5. 10 个经典PHP函数

    这篇文章主要介绍了php中的10个比较经典的函数,不太常见,可以满足有特殊需求的朋友 1. sys_getloadavg() sys_getloadavt()可以获得系 统负载情况.该函数返回一个包含 ...

  6. IImage--factory

    <?php /* 实例4 */ /* 使用工厂类解析图像工作 */ interface IImage { function getWidth(); function getHeight(); f ...

  7. 【leetcode刷题笔记】Merge Intervals

    Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[8,1 ...

  8. HDU OJ 2159 FATE

    #include <stdio.h> #include <string.h> ][] ; ]; //»ñµÃ¾­Ñé ]; //»¨·ÑµÄÈÌÄÍ¶È int main() ...

  9. 1.微信小程序-B站:前言准备

    前言 <微信小程序开发-B站>是以bilibili移动端网站为基础开发微信小程序版本,笔者喜欢的学习是愉快.轻松并能学到实战的东西,不知各位观友有没有一样的经历,就是一有问题不是先去Goo ...

  10. html符号实体

    对网页设计,软考有用的字符实体