码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1443 Joseph---约瑟夫环

时间:2018-04-01 01:00:14      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:现在   tar   clu   namespace   start   bsp   表示   const   star   

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1443

题目大意:

一共有2k个人,分别为k个好人和k个坏人,现在我们需要每隔m个人把坏人挑出来,但是条件是最后一个坏人挑出来前不能有好人被挑出来。。问最小的m是多少。k最大为13.

思路:

由于k的数值较小,直接打表就行。

对于约瑟夫环问题一般都是由0-n-1的下标,并且start = (start + m - 1)% n(n为当前的人数,n是会不断地变化的)这里的start是下标!!!不是具体的数值

举个例子:

6个人步数为5,初始化,start = 0

第一次:start = 0 + 5 - 1 % 6 = 4,下标为4的编号剔除

下标:0 1 2 3 4 5

编号:1 2 3 4 5 6

 

第二次:start = 4 + 5 - 1 % 5 = 3,下标为3的编号剔除

下标:0 1 2 3 4

编号:1 2 3 4 6

 

第三次:start = 3 + 5 - 1 % 4 = 3,下标为3的编号剔除

下标:0 1 2

编号:1 2 3 6

这里表示的都是下标的变化,题目要求前k个人不能先被剔除,只要下标start >= k一直成立就可以保证不会剔除前k个。因为如果每次的start >= k,说明提出的编号一定是>=k的(这里编号为k表示第k+1个人)

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 1e5;
 7 ll a[25];
 8 void init(int k)
 9 {
10     for(int ans = 0; ; ans++)//枚举步数
11     {
12         int start = 0;
13         int n = 2 * k;//2*k个人
14         bool ok = 1;
15         while(n > k)//输出前n个人即可
16         {
17             start = (start + ans - 1) % n;//这是下标,不是具体的数值,但是此处的下标必须大于等于k,这样才能保证前k个人不被剔除
18             //cout<<start<<endl;
19             if(start < k)//下标 < k,说明输出的一定是前k个人中的某一个
20             {
21                 ok = 0;
22                 break;
23             }
24             else n--;//满足的话,人数减一
25         }
26         if(ok)
27         {
28             a[k] = ans;
29             return;
30         }
31     }
32     return;
33 }
34 int main()
35 {
36     int n;
37     for(int i = 1; i <= 13; i++)init(i);
38     while(cin >> n && n)
39     {
40         cout<<a[n]<<endl;
41     }
42     return 0;
43 }

约瑟夫环传送门(等写到那个地方就开启传送门)

 

hdu1443 Joseph---约瑟夫环

标签:现在   tar   clu   namespace   start   bsp   表示   const   star   

原文地址:https://www.cnblogs.com/fzl194/p/8684818.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!