ZOJ 1088 System Overload
来源:互联网 发布:2016年母婴数据分析 编辑:程序博客网 时间:2024/04/26 09:03
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=88
题意:有几幢楼分别从1~n编号,现在1号楼首先断网,从下一幢未断网的楼从1开始数(数的是未断网的楼)到m,对数到m的楼进行断网,求当有n幢楼时,m是多少2号楼是最后断网的。
例:当n=10时,m=3,2号楼是最后断网的,断网顺序:1;4;7;10;5;9;6;3;2
解题思路:
有两种做法,一种是暴力的进行模拟,时间效率不高,另一种是用数学的方法做,也就是约瑟夫环问题,
//模拟做法
//Judge StatusProblem IDLanguageRun Time(ms)Run Memory(KB)//Accepted 1088 C++ 520 272#include <iostream>#include<cstdio>#include<cstring>using namespace std;int main(){ int n,i; bool cut[155]; while(scanf("%d",&n) && n!=0) { bool find=false;//表示是否成功 int m=1;//m从1开始模拟 while(!find) { memset(cut,true,sizeof(cut));//每次模拟对所有楼设为未断网 cut[1]=false;//1号楼首先断网 int before=1;//记录前一幢断网的楼号 int k=m;//k用于辅助 int num=n-1;//表示未断网的楼的数量 while(num!=1)//当未断网的楼只有一幢时此次m值的模拟结束,判断未断网的楼是否为2号来判断 { //这个m值是否成功 for(i=1;i<=k;i++ ) if(!cut[(before+i)%n])//在数的过程中遇到以断网的楼那么k的值需要加1,来跳过这幢楼 k++;//对于%n,因为是循环 before=(before+k)%n;//记录前一幢断网的楼 cut[before]=false;//把那幢楼状态设为断网 num--;//未断网楼数减1 if(cut[2]==false)//如果在模拟过程中遇到2号楼断网了那么这个m是错误的直接进行下一次模拟 break; k=m;//在模拟中为了跳过以断网的楼k值也许已经改变,但是再数下一幢时k要变成m再数 } if(cut[2]==true && num==1)//判断成功的条件 find=true; else m++; } printf("%d\n",m); } return 0;}
约瑟夫环:
首先明确约瑟夫环问题:约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
好了下面开始推公式:
给出一个序列,从0~n-1编号。其中,k代表出列的序号的下一个,即k-1出列。
a 0, 1, …, k-1, k, k+1, …, n-1
k-1出列后得到
b 0, 1…k-2,.k, k+1 ,….., n-1
对b进行转化一下,把0~k-2这串数列挪到k~n-1后面得到
b* k ,k+1 ,….n-1, 0, 1,….k-2
对b*数列进行一种映射:
k -----> 0
k+1 ------> 1
k+2 ------> 2
…..
n-1 ------>n-k-1
0 ------>n-k
1 ------>n-k+1
...
...
k-2 ------> n-2
也就形成c数列
C 0 ,1, 2,…., n-k-1, n-k, n-k+1, …….n-2
可以看出右边的值加个k对其取余(%n)就是左边的的值
这是一个n -1个人的问题,如果能从n -1个人问题的解推出 n 个人问题的解,从而得到一个递推公式,那么问题就解决了。假如我们已经知道了n -1个人时,最后胜利者的编号为x,那么他原本的编号就是(x+k)%n,也就是胜利者的编号。
其中k等于m % n。代入(x + k) % n <=> (x + (m % n))%n <=> (x%n +(m%n)%n)%n <=> (x%n+m%n)%n <=> (x+m)%n
假设第三轮的开始数字为B,那么这n - 2个数构成的约瑟夫环为B, B + 1, B + 2,......B - 3, B - 2.。继续做映射。
B -----> 0
B+1 ------>1
B+2 ------>2
...
...
B-2 ------> n-3
这是一个n - 2个人的问题。假设最后的胜利者为y,那么n -1个人时,胜利者为 (y + B) % (n -1 ),其中B等于m % (n -1 )。代入可得 (y+m) %(n-1)
要得到n - 1个人问题的解,只需得到n- 2个人问题的解,倒推下去。只有一个人时,胜利者就是编号0。下面给出递推式:
f [1] = 0;
f [ i ] = ( f [i -1] + m) % i;(i>1)
也许你会迷惑为什么%n变成公式中f[i]=(f[i-1]+m)%i中的%i?其实这个稍微想想就能明了。我们%n就是为了从序列c转换到序列b*——这是在n-1序列转换成n序列时%n;那么从n-2转换到n-1呢?不是要%(n-1)了吗?所以这个值是变量,不是常量。
好了公式推导完毕,下面回到这道题,依旧以n=10,m=3为例子,对他的映射转换过程具体分析。
首先1号楼直接断网,排除1号楼,映射关系从2号楼开始
红色数字表示2号楼在映射过程编号的变化,黄色数字表示下个断网楼号映射后的编号
第一次映射
2 - 0
3 - 1
4 - 2
5 - 3
6 - 4
7 - 5
8 - 6
9 - 7
10 - 8
第二次映射
3 0
4 1
5 2
6 3
7 4
8 5
0 6
1 7
第三次映射
3 0
4 1
5 2
6 3
7 4
0 5
1 6
第四次映射
3 0
4 1
5 2
6 3
0 4
1 5
第五次映射
3 0
4 1
5 2
0 3
1 4
第六次映射
3 0
4 1
0 2
1 3
第七次映射
3 0
0 1
1 2
第八次映射
0 0
1 1
第九次映射
1 0
最后总结:
2号楼最后映射关系后的编号肯定为0,因为只有他这么一幢楼,然后就是由后往前推,9次推后(n-1)它是否依旧是0
//公式//Judge StatusProblem IDLanguageRun Time(ms)Run Memory(KB)//Accepted 1088 C++ 0 272#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n;int judge(int m){ int f=0; //由于开始XWBy一号大楼开始直接出队,所以从2~n进行编号0~n-2 for(int i=2;i<n;i++) f=(f+m)%i; if(f==0)//编号为0,对应2号大楼 return 1; else return 0;}int main(){ while(scanf("%d",&n) && n!=0) { int m=1; while(!judge(m)) m++; printf("%d\n",m); } return 0;}
- zoj 1088 System Overload
- zoj-1088-System Overload
- zoj 1088 System Overload
- zoj 1088 System Overload
- ZOJ 1088 System Overload
- zoj--1088--System Overload
- ZOJ 1088 System Overload
- zoj 1088 System Overload
- ZOJ 1088 System Overload
- ZOJ 1088 System Overload
- ZOJ Problem Set - 1088System Overload
- 【zoj】System overload
- ZOJ 1088 System Overload (约瑟夫问题通用公式)
- TOJ 3053 OJ 2244 ZOJ 1088 System Overload / 约瑟夫
- ZOJ 1088 System Overload(约瑟夫问题通用公式)
- ZOJ--1088:System Overload(约瑟夫环问题)
- 【zoj】约瑟夫环相关- system overload
- System Overload
- 产品经理要懂多少技术?
- springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
- 读loki:TYPEList有感一
- 苹果MAC AIR MACOS X 10.8安装notes提示OS版本过低
- centos6.4 cacti的安装与配置
- ZOJ 1088 System Overload
- due date
- Mongo副本结点的相关配置
- cocos2d-x 3.0 事件分发机制 —触摸事件监听
- 安卓平台tess-two识别图片上的文字终于成功
- Redis中-Hashes数据类型
- 关于cocos2d和安卓 详细介绍
- 笔记:用前导零填充数字
- 微信图片上传到服务器