Joseph(进阶,动态规划)POJ---1012

传送门:http://poj.org/problem?id=1012

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.
Input: The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.
Output: The output file will consist of separate lines containing m corresponding to k in the input file.

Sample Input

3
4
0

Sample Output

5
30

题目大意:一群人围成环,其中一半为好人,一半为坏人,从其中一个人开始数,第m个人将被杀掉,上帝要惩罚坏人,因此在坏人死完之前,好人不能死去,问这个m是多少时满足题意。

解题思路: 我们将2k个人编号12k,前k个为好人,k+1到2k个是坏人。假设我们有6个人,13为好人,4~6为坏人,我们要求m,没啥好方法,只能去试探,m的范围在k+1到2k之间,我们可以手动推算一下,当m=4时,4死去是坏人,数列变为56123,下一个死去的是2,不满足。当m=5时,5死去,数列变为61234,下一个4死去,变为6123,再次变为123,坏人全部over,满足题意,可直接退出。当时就感觉肯定有规律,试了一晚上把规律给试出来了,贼开心。我们可以构造一个循环,找到此时的编号 n=(n+m-1)%(2k-out);
其中n为当前编号,算式里的n为上一步的编号,out为当前over的人数。其实我们可以想象一下,这个递推公式就是一段线段,然后在后面不断接减小的线段,直到变为k为止,那么这个长线段的长度为(k+1)
(k+2)*(k+3)……*k;(好吧,可能有点奇怪);

代码

#include<iostream>
#include<cstdio>
using namespace std;
int check(int m,int k)
{
	int out=0,now=0;
	while(out<k)
	{
		now=(now+m-1)%(2*k-out);
		out++;
		if(now<k) return 0;	
	}
	return 1;
}
int main()
{
	int k;
	while(scanf("%d",&k),k)
	{
		int m;
		for(m=k+1;;m++) if(check(m,k)) break;
		printf("%d\n",m);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值