【算法】<1>n_m问题

问题描述:n个人围成一个圈,顺序排号,从第一个人开始报数,输入整数m,凡是报到m的人都应该退出圈子,问最后留下的是原来第几号的那位?

以下是用c语言来写,仅仅用循环和数组来解决这个问题:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i,k,m,n,num[50],*p,key;
    scanf("%d%d",&n,&key);

    p=num;
    for(i=0;i<n;i++)
    {
        *(p+i)=i+1;

    }

    i=0; //i为每次循环时的计数变量
    k=0;//k为按1,2,3报数时的计时变量。
    m=0;//m为退出人数。
    while(m<n-1)  //模拟游戏过程,这里用退出人数来控制循环结束条件。
    {
        if(*(p+i)!=0)
            k++;
        if(k==key)
        {
            *(p+i)=0;  //表示该序号的孩子退出游戏。
            k=0;
            m++;
        }

        i++;

        if(i==n)  i=0; //由于是一个圈子,所以要用这种方式来返回
    }

    while(*p==0)  //这里需要注意由于前面用指针遍历数组的方式原因,p一直指向数组的第一个元素
        p++;  //这个做法是直接改变了指针的指向,而前面的做法并没有改变。

    printf("the last one is NO.%d\n\n",*p);
    return 0;
}

以下是c++语言,并且这里用到了链表,更加容易理解:
#include <iostream>
using namespace std;

struct linklist
{
    int idata;
    linklist *next;
};

linklist *present,*head;   //这里通过全局变量来建立两个不同函数之间的交流。。。

void creat(int n);
void gamestart(int n,int m);
int main()
{
    int m,n;
    cin>>n>>m;
    creat(n);
    gamestart(n,m);
    cout<<"第"<<present->idata<<"个孩子将获得胜利!"<<endl;
    return 0;
}

/*linklist* creat(int n)
{
    linklist *head,*p1,*p2;
    int i;
    p1=new linklist;
    p1->idata=1;
    head=p1;
    p2=p1;
    for(i=1;i<n;i++)
    {
        p1=new linklist;
        p1->idata=i+1;
        p2->next=p1;
        p2=p1;
    }
    p1->next=head;

    return head;
}*/

void creat(int n)
{

    int i;
    head=new linklist;
    head->idata=1;
    present=head;
    for(i=1;i<n;i++)
    {
        present->next=new linklist;
        present->next->idata=i+1;
        present=present->next;
    }

    present->next=head;

    present=head;

}

void gamestart(int n,int m)
{
    linklist *pguard;
    while(n!=1)//自己想到了结点个数,却没有想到怎么通过结点个数控制循环
    {
        int j;
        for(j=1;j<m;j++)     //这里的实现是一个关键。。。通过一个指针不断的在链表之间变化来模拟游戏过程。
        {
            pguard=present;
            present=present->next;
        }
        pguard->next=present->next;
        delete present;
        present=pguard->next;   //从删除结点的下一个节点接着开始循环。
        n--;
    }
}
以下是一个简单的向量类模板的 C++ 代码,可以实现数据的存储和访问,并且可以自动扩展内部存储空间。 ```cpp #include <iostream> #include <algorithm> template<typename T> class Vector { private: T* data; size_t size; size_t capacity; public: Vector() : data(nullptr), size(0), capacity(0) {} ~Vector() { if (data) { delete[] data; } } Vector(const Vector& other) : data(new T[other.capacity]), size(other.size), capacity(other.capacity) { std::copy(other.data, other.data + other.size, data); } Vector& operator=(const Vector& other) { if (this != &other) { T* new_data = new T[other.capacity]; std::copy(other.data, other.data + other.size, new_data); delete[] data; data = new_data; size = other.size; capacity = other.capacity; } return *this; } void add(const T& value) { if (size == capacity) { capacity = capacity ? capacity * 2 : 1; T* new_data = new T[capacity]; std::copy(data, data + size, new_data); delete[] data; data = new_data; } data[size++] = value; } void remove(size_t index) { if (index < size) { std::copy(data + index + 1, data + size, data + index); --size; } } T& operator[](size_t index) { return data[index]; } const T& operator[](size_t index) const { return data[index]; } size_t get_size() const { return size; } }; int main() { Vector<int> vint; size_t n, m; std::cin >> n >> m; for (size_t i = 0; i < n; ++i) { vint.add(i); } std::cout << vint.get_size() << std::endl; std::cout << vint[m] << std::endl; vint.remove(m); std::cout << vint.add(-1) << std::endl; std::cout << vint[m] << std::endl; Vector<int> vv = vint; std::cout << vv[vv.get_size() - 1] << std::endl; vv.add(m); std::cout << vint.get_size() << std::endl; return 0; } ``` 该向量类模板使用动态数组来存储数据,可以在 add() 方法中自动扩展内部存储空间,可以使用 [] 运算符来访问现有元素,并且可以使用 remove() 方法删除索引处从零开始的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值