SRM 147 2 600PeopleCircle


Problem Statement

There are numMales males and numFemales females arranged in a circle. Starting from a given point, you count clockwise and remove the K'th person from the circle (where K=1 is the person at the current point, K=2 is the next person in the clockwise direction, etc...). After removing that person, the next person in the clockwise direction becomes the new starting point. After repeating this procedure numFemales times, there are no females left in the circle.

Given numMalesnumFemales and K, your task is to return what the initial arrangement of people in the circle must have been, starting from the starting point and in clockwise order.

For example, if there are 5 males and 3 females and you remove every second person, your return String will be "MFMFMFMM".

Definition

  • ClassPeopleCircle
  • Methodorder
  • Parametersint , int , int
  • Returnsstring
  • Method signaturestring order(int numMales, int numFemales, int K)
(be sure your method is public)

Limits

  • Time limit (s)2.000
  • Memory limit (MB)64

Constraints

  • numMales is between 0 and 25 inclusive
  • numFemales is between 0 and 25 inclusive
  • K is between 1 and 1000 inclusive

Test cases

  1.  
    • numMales5
    • numFemales3
    • K2
     

    Returns"MFMFMFMM"

     
    Return "MFMFMFMM". On the first round you remove the second person - "M_MFMFMM". Your new circle looks like "MFMFMMM" from your new starting point. Then you remove the second person again etc.
  2.  
    • numMales7
    • numFemales3
    • K1
     

    Returns"FFFMMMMMMM"

     
    Starting from the starting point you remove the first person, then you continue and remove the next first person etc. Clearly, all the females are located at the beginning. Hence return "FFFMMMMMMM"
  3.  
    • numMales25
    • numFemales25
    • K1000
     

    Returns"MMMMMFFFFFFMFMFMMMFFMFFFFFFFFFMMMMMMMFFMFMMMFMFMMF"

  4.  
    • numMales5
    • numFemales5
    • K3
     

    Returns"MFFMMFFMFM"

     
    Here we mark the removed people with '_', and the starting position with lower-case:

    Number of      | People Remaining
    Rounds | (in initial order)
    ---------------+-----------------
    0 | mFFMMFFMFM
    1 | MF_mMFFMFM
    2 | MF_MM_fMFM
    3 | MF_MM_FM_m
    4 | M__mM_FM_M
    5 | M__MM__m_M
  5.  
    • numMales1
    • numFemales0
    • K245
     

    Returns"M"


This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.

 #include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <typeinfo>
#include <fstream> using namespace std;
char s[] ;
vector<int> g ;
int n ;
int k ; void dead (int id , int ans , int m)
{
for (int i = ans ; i <= n ; i ++) {
k = m % i ;
id = (id + k) % i ;
}
// printf ("id = %d\n" , id ) ;
g.push_back (id) ;
} void solve (int fmale , int m)
{
dead ( , , m ) ;
for (int i = ; i <= n ; i ++) {
k = m % i ;
int id = ( + k) % i ;
if (id - < ) id = id - + i ;
else id -- ;
dead (id , i + , m ) ;
}
reverse (g.begin () , g.end ()) ;
// for (int i :g ) printf ("%d " , i) ; puts ("") ;
for (int i = ; i < n ; i ++) {
if (i < fmale) s[g[i]] = 'F' ;
else s[g[i]] = 'M' ;
}
s[n] = '\0' ;
} class PeopleCircle {
public:
string order(int male , int fmale , int m) {
// printf ("\nmale=%d\nfmale=%d\nm=%d\n" , male , fmale , m) ;
g.clear () ;
n = male + fmale ;
solve (fmale , m) ;
return s;
}
}; // CUT begin
ifstream data("PeopleCircle.sample"); string next_line() {
string s;
getline(data, s);
return s;
} template <typename T> void from_stream(T &t) {
stringstream ss(next_line());
ss >> t;
} void from_stream(string &s) {
s = next_line();
} template <typename T>
string to_string(T t) {
stringstream s;
s << t;
return s.str();
} string to_string(string t) {
return "\"" + t + "\"";
} bool do_test(int numMales, int numFemales, int K, string __expected) {
time_t startClock = clock();
PeopleCircle *instance = new PeopleCircle();
string __result = instance->order(numMales, numFemales, K);
double elapsed = (double)(clock() - startClock) / CLOCKS_PER_SEC;
delete instance; if (__result == __expected) {
cout << "PASSED!" << " (" << elapsed << " seconds)" << endl;
return true;
}
else {
cout << "FAILED!" << " (" << elapsed << " seconds)" << endl;
cout << " Expected: " << to_string(__expected) << endl;
cout << " Received: " << to_string(__result) << endl;
return false;
}
} int run_test(bool mainProcess, const set<int> &case_set, const string command) {
int cases = , passed = ;
while (true) {
if (next_line().find("--") != )
break;
int numMales;
from_stream(numMales);
int numFemales;
from_stream(numFemales);
int K;
from_stream(K);
next_line();
string __answer;
from_stream(__answer); cases++;
if (case_set.size() > && case_set.find(cases - ) == case_set.end())
continue; cout << " Testcase #" << cases - << " ... ";
if ( do_test(numMales, numFemales, K, __answer)) {
passed++;
}
}
if (mainProcess) {
cout << endl << "Passed : " << passed << "/" << cases << " cases" << endl;
int T = time(NULL) - ;
double PT = T / 60.0, TT = 75.0;
cout << "Time : " << T / << " minutes " << T % << " secs" << endl;
cout << "Score : " << * (0.3 + (0.7 * TT * TT) / (10.0 * PT * PT + TT * TT)) << " points" << endl;
}
return ;
} int main(int argc, char *argv[]) {
cout.setf(ios::fixed, ios::floatfield);
cout.precision();
set<int> cases;
bool mainProcess = true;
for (int i = ; i < argc; ++i) {
if ( string(argv[i]) == "-") {
mainProcess = false;
} else {
cases.insert(atoi(argv[i]));
}
}
if (mainProcess) {
cout << "PeopleCircle (600 Points)" << endl << endl;
}
return run_test(mainProcess, cases, argv[]);
}
// CUT end

题意:n个人围成一圈,从编号为0的人开始报数1,后面的依次报2,3……当报道m时,该人离开圈子,他后面的一个人重新从1开始报数,以此类推……游戏最终会只有一个人留下来。这道题中我们需要得到的是每次离开之人的编号。(总人数n已知,m已知)。-------- 约瑟夫环问题,几乎是每个acmer的入门套餐。

上学期的时候,貌似用链表模拟做过,后来又用数学方法求过,但并不是很理解,如今又碰到了,便打算好好写份约瑟夫环报告。

从第一轮开始:

0 1 2 3 4 5 …… (n - 2)   (n - 1) 现在有n个人

明显第一次出队的人编号为m%n-1,我们令k = m % n ;

那么重新排列后为:

              k  k +1 k+2…… n-1     0     1     2      3    ……  k-2    

再把他们以0~n-1编号: 0  1   2   n-k-1   n-k  n-k+1  n-k+2 n-k+3     n-2

通过上下比对,我们能隐约发现前后存在一种映射关系,大概是(假设重新编号后,有个下标为id) id + k  ;

总之在算一下,其实是(id + k) % n ;

那么我们是不是能很容易的知道,现在的每个人在上一轮中存在的位置了吗?

求出每次游戏最后留下来的人是谁:

 #include<bits/stdc++.h>
int beg , m , n ;//从第beg个人开始数1,数到m的人离开,总人数为n。把他们从0~n -1编号。
int k ; void solve ()
{
int cur = ;
for (int i = ; i <= n ; i ++) {
k = m % i ;
cur = (k + cur ) % i ;
}
cur = (cur + beg ) % n ;
printf ("%d\n" , cur ) ;
} int main ()
{
while (~ scanf ("%d%d%d" , &beg , &m , &n) ) {
solve () ;
}
return ;
}

通过这个映射关系,我们还能求出:

每一轮出圈的人的编号。

 #include<bits/stdc++.h>
int m , n ;
int k ;
std::vector<int> g ; void dead (int id , int ans)
{
for (int i = ans ; i <= n ; i ++) {
k = m % i ;
id = (id + k) % i ;
}
g.push_back (id) ;
} void solve ()
{
dead ( , ) ;
for (int i = ; i <= n ; i ++) {
k = m % i ;
int id = ( + k) % i ;
id -- ;
if (id < ) id += i ;
dead (id , i + ) ;
}
std::reverse (g.begin () , g.end ()) ;
for (int i : g) printf ("%d," , i) ; puts ("") ;
} int main ()
{
while (~ scanf ("%d%d" , &m , &n)) {
g.clear () ;
solve () ;
}
return ;
}

看不懂的话,再结合这篇博文(orz):http://blog.csdn.net/u012333003/article/details/27076603

tc 147 2 PeopleCircle(再见约瑟夫环)的更多相关文章

  1. C#实现约瑟夫环问题

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace orde ...

  2. C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析

    尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这 ...

  3. C语言链表实现约瑟夫环问题

    需求表达:略 分析: 实现: #include<stdio.h> #include<stdlib.h> typedef struct node { int payload ; ...

  4. javascript中使用循环链表实现约瑟夫环问题

    1.问题 传说在公元1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的40 个同胞被罗马士兵包围.犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案.他们围成一个圈,从一个人开始,数到第 ...

  5. HDU 3089 (快速约瑟夫环)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3089 题目大意:一共n人.从1号开始,每k个人T掉.问最后的人.n超大. 解题思路: 除去超大的n之 ...

  6. 约瑟夫环(Josehpuse)的模拟

    约瑟夫环问题: 0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字. 这里给出以下几种解法, 1.用队列模拟 每次将前m-1个元 ...

  7. C++ 约瑟夫环问题

    约瑟夫环比较经典了 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直 ...

  8. 约瑟夫环的java解决

    总共3中解决方法,1.数学推导,2.使用ArrayList递归解决,3.使用首位相连的LinkedList解决 import java.util.ArrayList; /** * 约瑟夫环问题 * 需 ...

  9. 14.约瑟夫环问题[JosephusProblem]

    [题目] n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字).当一个数字删除后,从被删除数字的下一个继续删除 ...

随机推荐

  1. (译)你应该知道的jQuery小技巧

    帮助提高你jQuery应用的简单小技巧 回到顶部按钮 图片预加载 判断图片是否加载完 自动修补破损图像 Hover切换class类 禁用输入 停止正在加载的链接 toggle fade/slide 简 ...

  2. jQuery ajax - serialize() 方法-输出序列化表单值

    定义和用法 serialize() 方法通过序列化表单值,创建 URL 编码文本字符串. 您可以选择一个或多个表单元素(比如 input 及/或 文本框),或者 form 元素本身. 序列化的值可在生 ...

  3. Socket与SocketServer结合多线程实现多客户端与服务器通信

    需求说明:实现多客户端用户登录,实现多客户端登录一般都需要使用线程技术: (1)创建服务器端线程类,run()方法中实现对一个请求的响应处理: (2)修改服务器端代码,实现循环监听状态: (3)服务器 ...

  4. POJ 1947Rebuilding Roads(树形DP + 01背包)

    题目链接 题意:给出一个树形结构,求P个节点的子树最少要去掉几条边 分析:DP[root][j] 表示 以第 root 个为根节点, 包含j 个节点需要去掉几条边.那么对于 root 这个根节点来说, ...

  5. POJ3254Corn Fields(状态压缩DP入门)

    题目链接 题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一 ...

  6. python模块app登陆认证(M2Crypto数字证书加密)

    需求: 1.通过数字证书,非对称加密方式传送对称秘钥给服务端 2.用户名.密码使用对称秘钥加密,发送服务端验证 3.传送数据使用字节流方式 实现思路: 1.了解python的struct模块,用于字节 ...

  7. socket传数据并记录到文件中

    最近在新项目中要通过socket传一些数据,下面是程序: 功能: 将客户端发送的json数据写入到日志文件中,如果数据不是json的,丢弃. 程序如下: #!/usr/bin/env python # ...

  8. git的基本操作

    今天给同事培训了一下git的使用流程,简单记录一下 1,基本概念, 远程库和本地库. 2, git clone git://url/*.git clone远程的代码库到本地 3. 创建本地分支 当前是 ...

  9. bootstrap panel 和table的使用

    一.HTML中的页面内容 <div class="col-sm-12"> <!-- <div class="m-b-md" style= ...

  10. [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则

    [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则 转载请注明出处:http://www.codelast.com/ line search(一维 ...