zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/liyexin/p/13038864.html
Copyright © 2011-2022 走看看