HDU1443——约瑟夫问题

  题目

HDU1443——约瑟夫问题

时间限制:2000ms;空间限制:65536KB。
问题描述:约瑟夫问题是众所周知的。有n个人,编号为 1,2,⋯,n站在一个圆圈中,每隔m 个人就杀一个人,最后仅剩下一个人。约瑟夫很聪明,可以选择最后一个人的位置,从而挽救他的生命。例如,当n=6 且m=5时,按顺序出列的人员是 5,4,6,2,3,1,那么1会活下来。
假设在圈子里前面怡好有 k 个好人,后面恰好有 k 个坏人,则必须确定所有坏人都在第一个好人前面被杀的最小m。
输入格式:输入文件中包含若干行,每行一个k,最后一行为 0,可以假设0<k<14。
输出格式:输出文件中每行给出输人文件中的 k 对应的最小m。
输人样例:
3
4
0
输出样例:
5
30 

思路 

  1. m 表示隔几个人杀人,因为需要坏人全部先被杀,所以 m 从 k+1 开始递增
  2. leave 表示存活下来的人数,最开始有 2 * k 个人,直到小于 k 时退出循环(如果leave 小于 k 就说明有好人被杀了,所以leave 不能小于 k)
  3. p 代表一个指针,最开始指向第一个人(下标是 0),要隔 m 个人杀一个人就让 (p+m-1)%leave(取模是为了防止越界), p 表示要杀的人的下标
  4. 如果发现这个下标 p 小于 k,就说明杀的是好人,就退出内层循环,让m++
  5. 如果发现 leave(存活下来的人数)等于 k,就说明坏人全部被杀了,留下来的都是好人,就把 m 返回

代码 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            int k = sc.nextInt();
            if (k == 0) {
                break;
            }
            System.out.println(Joseph(k));
        }
    }

    public static int Joseph(int k) {
        int leave, p;
        for (int m = k + 1; ; m++) {
            for (leave = 2 * k, p = 0; k < leave; leave--) {
                p = (p + m - 1) % leave;
                if (p < k) {
                    leave = 0;
                }
            }
            if (leave == k) {
                return m;
            }
        }
    }
}

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值