约瑟夫环 POj 3517 HOJ 1017

深入理解 JVM 原理
深入理解 JVM 原理
wangxiaoming

                                               约瑟夫环  POJ 3517 HOJ  1017 

POJ 3517: 
题目大意: 给定三个数n , k , m   , m 表示的是从第m  个人 开始 然后每隔 k -1个人就 杀掉,最终只有 1个人

解题思路: 这个起点不是从0 开始的怎么办,倒过来算最后一个活着的人是怎么确定 值能让循环进行到N-1 那么最后一个就有着落了

代码:已经AC掉
#include<iostream>
using namespace std;

int main()
{//题目大意是从M 个人开始杀人然后每隔k 个人 杀掉

    int m , k , n;
    while(cin>>n>>k>>m)
    {
        int s = 0;  //从最后一个人假设最后一个人为0
        if(k == 0 && n == 0 && m == 0) break;
        //为什么下面值进行到n -1 次就停了因为第一次不是从地狱歌人开始的
        for(int i = 2 ; i < n; i++)
        {
            s = (s+k)%i ;
        }
        cout<<(s+m)%n +1<<endl;
    }
    return 0;
}



题目大意: 在约瑟夫环中有k 个坏人 k 个号人 现在要求 所有的坏人要死在第一个好人的前面 也就是说每次只杀掉bad guy 不杀掉good guy 


解题思路: 一看,靠太他妈复杂了怎么解? 求大神啊! 有k 个好人k个坏人 总人数n又没有 这里貌似总人数就是k*2 (k + k 嘛 )其次就m 了表示的是每隔 m-1个人就杀掉一个
      也就是说从这个人被杀到下一个被杀中间有m-1个人  好吧如何求最小的m 
     首先意味着只进行了k 论循环因为只杀掉 k 个坏人 其次如何做到每次杀掉的是坏人呢? 我而且人又是怎样站成圈的呢?
      突发此想,好无语怎么做, 一直从0 到k-1一直杀下去 到 k 时好人出现了 但是m 又怎么算 这次杀掉的人是j  下一个人是( j+m)%i 
       约瑟夫问题不就是倒过来的嘛 也就是说从最后一次流下做好一个人 那么由后往前杀掉 k-1 个好人 最后再杀坏人,然后一直杀掉的坏人
      杀人可以 每几个人杀掉一个人 怎么办 ? 计算机部就能计算嘛, 用个暴力 循环m 下,那么出循环的条件呢,那就是刚好杀到坏人了
      其次在 要求杀 k -1 个好人  那有怎么办 ?而且怎么知道好人已经杀完了?
      最后那个好人是第几次杀掉的 ?也就是序列号为  1 的那个号人 是第几次 挂掉的?  最后剩下的是 k 个坏人 1 个好人那么就是 k + 1 次杀掉的 如 i = 2 也就是说最后只剩下两个人 那么就for(i = 2; i <= n; i++)
      要只要杀掉k-1 个人 怎么办 好办  只要执行k -1此循环就好执行k 次循环那么就要开始杀坏人了 那么怎么判断杀掉好人期间不杀掉坏人 用一个条件判断语句来 当 j >= k 那么循环跳出 进行下一个循环
        但是这样没杀完就跳出,又要担心好人没杀完,怎么办 再加一个循环 从1 开始杀 从2 开始杀,然后所有的全部杀掉。。。
现在给出上面的暴力解法:
不过一要说的是超出了时间限制

#include<iostream>
using namespace std;

int main()
{
    int k , j, di;
    int i ;
    while(cin>>k)
    {
        if(k == 0) break;
        int m ;
        for(m = 1; ;m++)
        {
           for(di = 0; di< k; di++)
           {//最终把k-1 个恩全部杀掉 而且经k 重循环之后得到的就是k了
                 //首先值进行了k 个循环杀人
                j =  di;
                for(i = k+1; i <= 2*k; i++)
                {//开始杀掉好人杀到头
                    j = (j + m)%i;
                }
                //上面有要开始担心没有杀掉因此很有可能是取的第一个杀掉的位置不合理那么从新选取di再开始杀人
                if(j >= k)
                {
                    break;
                }

           }
           if(di == k)
           {//成立说明了刚好杀到第k个坏人了如果不成立说明 m 选择不合理重新来
               cout<<m<<endl;
               break;
           }

        }

    }

    return 0;
}


      

 
wangxiaoming CSDN认证博客专家 架构 Spring Boot Redis
博客是很好的总结和记录工具,如果有问题,来不及回复,关注微信公众号:程序员开发者社区,获取我的联系方式,向我提问,也可以给我发送邮件,联系 1275801617@qq.com
©️2020 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值