约瑟夫问题(猴子选大王)

n只猴子要选大王,选举方法如下:所
有猴子按 1,2 ……… n 编号并按照顺序围成一圈,
从第 k 个猴子起,由1开始报数,报到m时,该猴子就跳出圈外,
下一只猴子再次由1开始报数,
如此循环,直到圈内剩下一只猴子时,这只猴子就是大王。

 

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int m,n;
    cin>>m>>n;
    vector<int> v;
    for(int i=1; i<=m; i++)
    {
        v.push_back(i);
    }
    int t=1;
    while(m>1)
    {    
        t+=n-1;
        t=!(t%m)?m:t%m;
        v.erase(v.begin()+t-1);    //删除当前vector中第t个元素
        m--;
    }
    cout<<v[0]<<endl;
    return 0;
}

 

 

 下面这种大同小异,只不过更容易理解

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int m,n;
    cin>>m>>n;
    vector<int> v;
    for(int i=1; i<=m; i++)
    {
        v.push_back(i);
    }
    int t=1;
    while(v.size()>1)
    {    
        t+=n-1;
        t=!(t%v.size())?v.size():t%v.size();
        v.erase(v.begin()+t-1);    //删除当前vector中第t个元素
    }
    cout<<v[0]<<endl;
    return 0;
}

 

下面是用C语言写的,没有任何技巧性

#include<stdio.h>
#define Maxsize 100
double max_min(int i, int* a)
{
    int m, n, r;
    int *p, *q;
    double s = 0, min, max, maxmin;
    for (m = 2; m <= i; m++)  //子列长度
    {
        p = a;    //子列首元素指针
        q = a;
        for (n = 1; n <= i - m + 1; n++)   //子列起始位置
        {            
            for (r = 1; r < m; r++)     
            {
                q++;
                max = (double)*p;
                min = (double)*p;
                if (max<*q)
                    max = *q;
                if (min>*q)
                    min = *q;                
            }    
            p++;
            q = p;
            maxmin = max - min; 
            s += maxmin;
        }
    }
    return s;
}


int main()
{
    int i, j;
    double s;
    int a[Maxsize];
    scanf("%d", &i);
    for (j = 0; j<i; j++)
    {
        scanf("%d", &a[j]);
    }
    s = max_min(i, a);
    printf("s=%lf\n", s);    
    return 0;
}

 

其实题目的思想很简单,但是花了两个多小时才完成!!!

突破口1:一点点数学技巧

突破口2:使用vector容器

 

第一次看到题目后就想到了list,折腾了一个多小时还是不行,不得不转变思路。。

于是用了和数组最相近的vector容器,还真就成功了,哈哈!!

 

 

 

##############################这是分界线,是不一样的我##########################################

 

 

2016.4.21

上面的几个代码都是模拟法,复杂度为log(nm)面对大数据就心有余而力不足了……

今天在hihocoder上面看到约瑟夫问题,可以进行bp优化的~优化后为log(n),爽

//约瑟夫问题dp优化 
#include<iostream>
using namespace std;
int k;

int fun(int n){
    if(n == 1)
        return 0;
    else if(n <= k)
        return (fun(n - 1) + k) % n;
    else{
        if(fun(n - n / k) < n % k)
            return n - n % k + fun(n - n / k); 
        else
            return fun(n - n / k) - n % k + (fun(n - n / k) - n % k) / (k - 1);
    }
}

int main(){
    int T, N;
    cin >> T;
    while(T--){
        cin >> N >> k;
        cout << fun(N) << endl;
    }    
    return 0;
} 

 

posted @ 2015-11-06 21:20  Nagihiko  阅读(590)  评论(0编辑  收藏  举报