UVA 133 The Dole Queue 约瑟夫问题的变种,手写链表,模拟

来源:互联网 发布:自己设计字体的软件 编辑:程序博客网 时间:2024/05/06 09:32

连约瑟夫问题的公式都不会,更何况变种了,只好手动模拟

好吧,我确实想到了删除一个数就把它置为0,然后要走的时候再判断...

可是我觉得一旦n变大了,这种方法需要的时间也随之上升,因此手写一个链表来走好了

le[i]代表第i个元素左边的元素的下标,ri[i]代表第i个元素右边元素的下标 ,sz表示链表里还有多少元素。

不过因为我的实现的缘故,依然要把删除的元素置为0,不过我觉得还是比原来的方法要快

删除的时候只要修改左边元素的ri和右边元素的le就好了,以下是代码

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;int n,k,m,arr[25],be,ed,le[25],ri[25],sz;int main(){    while(scanf("%d%d%d",&n,&k,&m)==3&&n){        sz=n;        for(int i=0;i<n;++i)            arr[i]=n-i,le[i]=(i-1+n)%n,ri[i]=(i+1)%n;        be=n-1,ed=0;        while(sz){            for(int i=1;i<k;++i)                be=le[be];            for(int i=1;i<m;++i)                ed=ri[ed];            if(sz==1&&be==ed){                printf(" %2d\n",arr[be]);                break;            }            else if(sz==2&&be!=ed){                printf(" %2d %2d\n",arr[be],arr[ed]);                break;            }            else if(be==ed){                printf(" %2d,",arr[be]);                --sz;                arr[be]=0;                ri[le[be]]=ri[be];                le[ri[be]]=le[be];                while(!arr[be])                    be=le[be];                while(!arr[ed])                    ed=ri[ed];            }            else{                printf(" %2d %2d,",arr[be],arr[ed]);                arr[be]=arr[ed]=0;                sz-=2;                ri[le[be]]=ri[be];                le[ri[be]]=le[be];                ri[le[ed]]=ri[ed];                le[ri[ed]]=le[ed];                while(!arr[be])                    be=le[be];                while(!arr[ed])                    ed=ri[ed];            }        }    }    return 0;}


0 0