• UVA133(约瑟夫环变种)


    地址:https://vjudge.net/problem/UVA-133

    题目描述

    为了缩短领救济品的队伍,NNGLRP决定了以下策略:每天所有来申请救济品的人会被放在一个大圆圈,面朝里面。选定一个人为编号 1 号,其他的就从那个人开始逆时针开始编号直到 N。一个官员一开始逆时针数,数 k 个申请者,然后另一个官员第 N 个始顺时针方向数 m 个申请者,这两个人就被送去再教育。如果两个官员数的是同一个人,那个人则被送去从政,然后2个官员再在剩下的人里面继续选直到没人剩下来,注意两个被选 中的人是同时走掉的,所以就有可能两个官员选中一个人。

    Input

    输入含有多组测试资料,每组测试资料一列含有三个数 N,k 和 m(k, m > 0,0<N<20)。 当输入为 0 0 0 代表输入结束。

    Output

    对每组测试资料输出一列。输出被选中的申请者的编号顺序(一对一对的)。每个数的宽度为 3 。每一对前面的那个编号为逆时针数的官员选出的,后面的那个编号为顺时针数的官员选出的(但是如果这2个官员选出同一个人,那就只会有一个编号)。每一对 之间以逗号分开。格式请参考Sample Output。

    Sample Input

    10 4 3 
    13 17 42
    7 8 47
    0 0 0

    Sample Output

     4 8, 9 5, 3 1, 2 6, 10, 7 
    4 11, 10 1, 8 6, 13 7, 3, 5 12, 9 2
    1 3, 5 7, 2 4, 6



    解析:
    模拟,但坐标变换非常重要。
    两套代码:
    #include <bits/stdc++.h>
    using namespace std;
    int n,k,m;
    int a[30];
    int go(int p,int d,int t)
    {
        while(t--)
        {
            do
            {
                p=(p+d+n-1)%n+1;//刘汝佳代码的巧妙之处
            }while(a[p]==0);
        }
        return p;
    }
    main()
    {
        while(cin>>n>>k>>m&&n)
        {
             for(int i=1;i<=n;i++)
             a[i]=i;
             int left=n;int p1=n;
             int p2=1;
             while(left)
             {
                 p1=go(p1,1,k);
                 p2=go(p2,-1,m);
                 printf("%3d",p1);
                 left--;
                 if(p2!=p1)
                 {
                    printf("%3d",p2);
                     left--;
                 }
                 a[p1]=a[p2]=0;
                 if(left)
                 cout<<",";
             }
             cout<<endl;
        }
    }
    更易于理解的代码:
    #include<iostream>
    #include<cmath>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=30;
    int vis[maxn];
    int n,k,m;
    int main()
    {
        while(scanf("%d%d%d",&n,&k,&m)==3&&n)
        {
        //    vector<int>vis(n);
            memset(vis,0,sizeof(vis));
            int ki=0,mi=n-1,cnt=0,cntk=0,cntm=0;
            while(cnt<n)
            {
                while(1)
                {
                    if(vis[ki]!=-1)
                        cntk++;
                    if(cntk==k)
                        break;
                    ki=(ki+1)%n;
                }
                while(1)
                {
                    if(vis[mi]!=-1)
                        cntm++;
                    if(cntm==m)
                        break;
                    mi=(mi+(n-1))%n;  //顺时针,+代替-
                }
                if(ki==mi)
                {
                    vis[ki]=-1;
                    cnt++;
                    printf("%3d%s",ki+1,cnt==n?"":",");
                }
                else
                {
                    vis[ki]=-1;
                    vis[mi]=-1;
                    cnt+=2;
                    printf("%3d%3d%s",ki+1,mi+1,cnt==n?"":",");
                }
                cntk=0,cntm=0;
            }
            cout<<endl;
        }
    }
  • 相关阅读:
    vscode snippet
    OpenGL Type
    [转] fio参数详解
    [转] openchannel SSD( OCSSD)
    [转]linux内存管理
    proc/meminfo && hugepage
    [转] 从free到 page cache
    [转]linux网络协议栈(1)——链路层
    [转]linux 网络协议栈(1)——网络设备
    [转]linux网络协议栈(1)——socket buffer
  • 原文地址:https://www.cnblogs.com/liyexin/p/13038864.html
Copyright © 2020-2023  润新知