C++经典题目:约瑟夫环问题
问题描述:
有n个人围成一圈,顺序排号。从第一个人开始报数(1~3报数),凡报到3的人退出圈子,问最后留下的人原来排在第几号。
分析:
首先由用户输入人数n,然后对这n个人进行编号【因为如果不编号的话,我们就不能知道最后是哪位童鞋留下来了:)】
然后就开始了一圈一圈的循环,不断形成新的圈子,不断有人被淘汰,那么循环到什么时候截止呢?对只剩最后一个人,也就是说淘汰n-1了个人的时候,这个时候停止循环。
在实际情况中,应该是这n个人一开始围成了一个大圈子,然后随着不断的淘汰,圈子不断减小,最后剩下的那个人的一开始的编号就是我们要的结果。
我在用数组来表示这些人,因为进行了初始化,所以数组中元素的值都是原来的编号,因此我们只需要将被淘汰的人对应的数组元素的值设置为0即可。然后随着不断的循环,最后只剩下一个值不为0的数组元素,这个元素就是我们要的结果。
程序代码
#include<iostream> using namespace std; int main() { int i; //i用来记录数的那个数字 int k,j; //k用来记录淘汰的人数 ,j用来表示第j个人 int Array[10]; //对10个人进行编号 for(i=0;i<10;i++) { Array[i]=i+1; } i=1; k=0; /*因为n个人围成一个圈,所以当j>n的时候,j要除n取余,例如(n+1)%n=1 之所以要++j,而不是j++是因为要先加1再判断*/ for(j=0;k<9;j=++j%10) { if(Array[j]!=0)//当j对应的人没有被淘汰时参与进来,淘汰的直接忽略 { if(i==3) //当j对应的人数到m的时候 { k++; //淘汰人数加1 Array[j]=0; //对应数组中的数据置为0 i=1; //重新开始报数 } else { i++; //当j对应的人数没有数到m,则进行下一个 } } } for(i=0;i<10;i++) { if(Array[i]!=0)//通过上面的操作,所有淘汰的人员数组对应的值都为0,不为0的就是留下来的 { cout<<"留下来的是,第"<<i+1<<"个人"<<endl; } } cout<<endl; return 0; }
一些扩展
我们可以对上述程序做一些扩展,让用户输入总人数和用于淘汰的那个数字。#include<iostream> using namespace std; int main() { int i; //i用来记录数的那个数字 int n,m; int k,j; //k用来记录淘汰的人数 ,j用来表示第j个人 cout<<"请输入总人数n和用于淘汰的数字m:"; cin>>n>>m; int *Array=new int[n]; //对n个人进行编号 for(i=0;i<n;i++) { Array[i]=i+1; } i=1; k=0; /*因为n个人围成一个圈,所以当j>n的时候,j要除n取余,例如(n+1)%n=1 之所以要++j,而不是j++是因为要先加1再判断*/ for(j=0;k<n-1;j=++j%n) { if(Array[j]!=0)//当j对应的人没有被淘汰时参与进来,淘汰的直接忽略 { if(i==m) //当j对应的人数到m的时候 { k++; //淘汰人数加1 Array[j]=0; //对应数组中的数据置为0 i=1; //重新开始报数 } else { i++; //当j对应的人数没有数到m,则进行下一个 } } } for(i=0;i<n;i++) { if(Array[i]!=0)//通过上面的操作,所有淘汰的人员数组对应的值都为0,不为0的就是留下来的 { cout<<"留下来的是,第"<<i+1<<"个人"<<endl; } } cout<<endl; return 0; }
11计信班赵哲