Roman Roulette(约瑟夫环模拟)
Roman Roulette
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 286 Accepted Submission(s): 105
Having read an account of this gruesome event you become obsessed with the fear that you will find yourself in a similar situation at some time in the future. In order to prepare yourself for such an eventuality you decide to write a program to run on your hand-held PC which will determine the position that the counting process should start in order to ensure that you will be the sole survivor.
In particular, your program should be able to handle the following variation of the processes described by Josephus. n > 0 people are initially arranged in a circle, facing inwards, and numbered from 1 to n. The numbering from 1 to n proceeds consecutively in a clockwise direction. Your allocated number is 1. Starting with person number i, counting starts in a clockwise direction, until we get to person number k (k > 0), who is promptly killed. We then proceed to count a further k people in a clockwise direction, starting with the person immediately to the left of the victim. The person number k so selected has the job of burying the victim, and then returning to the position in the circle that the victim had previously occupied. Counting then proceeeds from the person to his immediate left, with the kth person being killed, and so on, until only one person remains.
For example, when n = 5, and k = 2, and i = 1, the order of execution is 2, 5, 3, and 1. The survivor is 4.
Your program may assume a maximum of 100 people taking part in this event.
1 5
0 0
历史学家弗拉维·约瑟夫曾讲述过这样的故事:在公元前67年的罗马犹太战争中,罗马攻下了他掌权的城市。随后,他与另外40个反抗战士一起逃到了一个山洞中而被困在里面。罗马人发现了他的下落并劝他投降,但他的战士们拒绝投降。于是他提议互相杀死对方,一个接一个,顺序由大家决定。有一种传统的方式,即为了公平起见所有人都站成一个环,从某一点开始,循环计数,每隔两个活着的人就杀掉一个。最后只有约瑟夫幸存了下来,投降了罗马。问题来了,约瑟夫如何知道一开始站第31位才会幸存到最后呢?是不是趁着洞穴黑暗大家没注意,悄悄地用41个石子演练过了?还是他用数学方法计算出了这个位置?
在仔细读过这个故事由来后,你逐渐克服了恐惧心理,不再害怕将来这种事会发生到你的头上。但为了应对这种类似的情况,你准备为你的手机写一个程序,以便快速的计算这个过程并确保你能站到最后幸存的位置上。
类似于约瑟夫所述的问题,你的程序需要处理如下改编过的问题。最初n(n > 0)个人面朝内围成一个环,并依次按顺时针编号1到n。你的编号为1,第一个轮到的人编号为i,同样顺时针方向开始计数,直到第k(k > 0)个人把他杀掉。然后再从下一个还活着的人开始向后数到第k个人,由这个人来把刚才杀掉的人埋葬,并站到被杀的人的位置上。然后再从他左面第一个还活着的人开始计数,杀掉第k个人,以此类推,直到只有一个人还活着。
比方说,n = 5,k = 2,i = 1,被杀的顺序应为:2、5、3和1。4幸存。
分析
类似于经典的约瑟夫环问题,这类问题都是可以用数学推导求出通式的。但这道题目的过程要远比约瑟夫环问题复杂得多,分析通式比较困难,且由于数据量很小(少于100人),可直接按模拟类型的题目对待求解。
模拟的实现使用动态数组是非常方便的,过程也很简单。数组初始存储每一个人的编号,从第0个元素(1号)开始计数,每次杀死一个人前先不要将这个人的编号删除,而是先找出要来埋他的人,将他们的编号互换,然后将埋他的人原来所在的位置删掉即可。最后计算出的是从1号开始计数,最后能幸存的人编号p,那么从你前面第p个人开始你就是安全的(你站在第1位),即n – p。这个换算的原理是显而易见的。
这个是找你前面第p个人开始你就是安全的;
由这个人来把刚才杀掉的人埋葬,并站到被杀的人的位置上
题解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define mem(x,y) memset(x,y,sizeof(x))
/*#define L tree[root].l
#define R tree[root].r
#define S tree[root].sum
#define NOW tree[root<<1].sum+tree[root<<1|1].sum
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r*/
using namespace std;
const int INF=0x3f3f3f3f;
vector<int>vec;
int main(){
int n,k,flot=;
while(scanf("%d%d",&n,&k),n|k){
vec.clear();
for(int i=;i<=n;i++)
vec.push_back(i);
int pos=,kisp=(k-)%vec.size();
while(vec.size()>){
pos=(kisp-+k)%(vec.size()-);
pos=(pos+(pos>=kisp))%vec.size();
vec[kisp]=vec[pos];
vec.erase(vec.begin()+pos);
kisp=(kisp+k-(pos<kisp))%vec.size();
}
printf("%d\n",(n - vec.front() + ) % n + );
//printf("Case %d: %d\n",++flot,*vec.begin());
}
return ;
}
Roman Roulette(约瑟夫环模拟)的更多相关文章
- uva 133 The Dole Queue 双向约瑟夫环 模拟实现
双向约瑟夫环. 数据规模只有20,模拟掉了.(其实公式我还是不太会推,有空得看看) 值得注意的是两个方向找值不是找到一个去掉一个,而是找到后同时去掉. 还有输出也很坑爹! 在这里不得不抱怨下Uva的o ...
- 10行Python代码解决约瑟夫环(模拟)
http://blog.csdn.net/dengyaolongacmblog/article/details/39208675 #!/usr/bin/env python # coding: utf ...
- 约瑟夫环(Josehpuse)的模拟
约瑟夫环问题: 0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字. 这里给出以下几种解法, 1.用队列模拟 每次将前m-1个元 ...
- hdu 4841 圆桌问题(用vector模拟约瑟夫环)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4841 圆桌问题 Time Limit: 3000/1000 MS (Java/Others) M ...
- UVa 130 - Roman Roulette
模拟约瑟夫环 Roman Roulette The historian Flavius Josephus relates how, in the Romano-Jewish conflict o ...
- tc 147 2 PeopleCircle(再见约瑟夫环)
SRM 147 2 600PeopleCircle Problem Statement There are numMales males and numFemales females arranged ...
- 14.约瑟夫环问题[JosephusProblem]
[题目] n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字).当一个数字删除后,从被删除数字的下一个继续删除 ...
- Java学习之约瑟夫环的两中处理方法
package day_2; import java.util.Scanner; /** * @author Administrator * 约瑟夫环问题: 设编号为 1,2,3,....n的N个人围 ...
- 约瑟夫环问题及python与c++实现效率对比
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重 ...
随机推荐
- R与数据分析旧笔记(十七) 主成分分析
主成分分析 主成分分析 Pearson于1901年提出的,再由Hotelling(1933)加以发展的一种多变量统计方法 通过析取主成分显出最大的个别差异,也用来削减回归分析和聚类分析中变量的数目 可 ...
- printf与scanf的返回值、注意点
printf()的返回值为其输出字符串常量的字符数(注意字符数与字数的区别)注意计数针对所有的打印字符,包括空格和不可见的换行字符(不包括字符串的空字符). scanf()函数返回成功读入的项目的个数 ...
- ortoiseSVN无法编辑日志信息的解决方法
提交时忘记编写日志,想重新编辑日志信息,弹出错误提示: DAV 请求失败:可能是版本库的 pre-revprop-change 钩子执行失败或者不存在 至少有一个属性变更失败:版本库未改变 设置属性 ...
- 解决:eclipse导入android时工程下没有R文件的问题,以及style.xml文件报错
解决:eclipse导入android时工程下没有R文件的问题,以及style.xml文件报错
- JWPlayer 初探
http://www.360doc.com/content/13/0103/22/21412_258041878.shtml JWPlayer 是一款比较实用的web flash 播放器
- android -上传文件到服务器
android上传文件到服务器 重点:最好是设置好content-type这些参数的配置! package com.spring.sky.image.upload.network; ...
- Java 根据comboBox选择结果显示JTable
处理这样的问题的主要思路是: 对于JTable,JTree等Swing控件,都有一个对应的Model用来存储数据,JTable对应的有一个DefaultTableModel. Defa ...
- Thread’s start method and run method
工作中用到了Thread,一开始用错了,仔细研究了一下,稍作整理. 前言,今天写代码居然这样写的 new Thread() { @Override public void run() { System ...
- Struts2 学习笔记20 类型转换part2 写自己的转换器
之前说的是调用Struts2的默认转换器,现在我们来说以下写自己的转换器,这个一般不常用,在访问不是自己写的类中可能用到.我们一点点来,因为写自己的转换器需要注意的东西还是很多的. 我们还是用之前的项 ...
- c/c++中宏定义##连接符 和#符的使用
C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结.关于#和##在C语言的宏中,#的功能是将其后面的宏 ...