Power Crisis -> 约瑟夫问题

UVA 151 Power Crisis

题目简述:一个地区需要进行能源限制,因此需要对所有的街道 N 进行轮流停电,为了公平起见,每隔 m-1 个街道就进行停电。例如,N=17,m=5时,得到的停电顺序为:1,6,11,16,5,12,2,9,17,10,4,15,14,3,8,13,7。 问每次都从1开始,到13街区截止的情况下,m 最小是多少。
这个问题是约瑟夫问题的改版。约瑟夫问题可以简单的理解为就是一群人站成一圈,每个报数为 m 的人离开这个圈子,问最后剩下的那个人是编号几。
约瑟夫问题有两种解法,第一种为链表法,但是缺点是时间复杂度达到了 O(nm),另一种是用 dp 的想法,有一个递归公式 f(n) = [f(n-1)+m]%n。这个公式可以这样理解,我们首先要先明确,在给定 n 和 m 的情况下,不管进行了几轮的报数,最终活下来的都是同一个人。那么以此为基础。假设 甲1,甲2,甲3,甲4,甲5,这五个人,每次叫到2的人就离开,那么第一个离开的就是甲2,下一轮报数的时候就会变成是甲3,甲4,甲5,甲1。第二轮报数的时候,可以想象成后面的人往前移动了m个位置。这就说明了一个问题,每经过一轮,最终活下里的那个人,他的编号就会往前 m 个。
有了上面的想法,我们反过来想就变成,人数每增加一个,那么最终活下来的那个人的编号就要往后 + m,因为是循环的形式,所以我们 % n。
代码如下:
#include<iostream>
using namespace std;

int main(){
    int N = 0;
    while(cin>>N && N){
        for(int m=1; ; m++){
            int temp=0; 
            for(int n=1; n < N; n++){
                temp=(temp+m)%n;
            }
            if(temp==11){
                cout << m << endl;
                break;
            }
        }
    }
    return 0;
}
补充一下,还有一些我曾经写过的题目,在我的 github 上可以找到,也许你们也可以参考一下。

https://github.com/zzybccdb/GPE_problem

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值