
设n=100,c=1,m=10.
(1)将1到n个人的序号存入一维数组p中;
(2)若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置;
(3)重复第(2)步直至圈中只剩下p[1]为止。
部分源程序已给出。
请勿改动主函数main()和输出数据函数writeDat()的内容。 #include <stdio.h>
#define N 100
#define S 1
#define M 10int p[100],n,s,m
void WriteDat(void)void Josegh(void)
{}void main()
{
m=M
n=N
s=S
Josegh()
WriteDat()
}void WriteDat(void)
{
int i
FILE *fp
fp=fopen("out.dat" ," w" )
for(i=N-1i>=0i--){
printf(" %4d" ,p[i])
fprintf(fp," %4d" ,p[i])
if(i % 10==0){
printf("\n" )
fprintf(fp, "\n" )
}
}
fclose(fp)
}
/* 注:题中第一个for()循环是先对数组p赋初值。在第二个for()中用i来控制没出圈的
总人数,s1=(s1+m-1)%i的作用是找出报数后出圈人的下标,其中对i求余的作用是使报
数按圈进行(即报到尾后又从头报),该算法在很多题目中都用到。由于求余的作用当
报数正好到最后一个时s1为0,故而要进行if(s1==0)的判断。内嵌的for()循环是将出圈
以后的人依次往前移。*/
void Josegh(void)
{
int i,j,s1,w
s1=s
for(i=1i<=ni++)
p[i-1]=i
for(i=ni>=2i--)
{s1=(s1+m-1)%i<br>if(s1==0)<br>s1=i<br>w=p[s1-1]<br>for(j=s1j<ij++)<br>p[j-1]=p[j]<br>p[i-1]=w<br>}
} 这的问题和这个一样,看看吧,应该能解决了
法一(模拟法):
#include<iostream>using std::cin
using std::cout
int main()
{
int n,m
cout<<"请输入n= "
cin>>n
if(n<1)
{
cout<<"n必须大于1!\n请重新输入n= "
cin>>n
}
cout<<"请输入m= "
cin>>m
bool * a = new bool [n+1]
a[0]=false
for(int i=1i<n+1i++)
a[i]=true
int x,k=nx=i=0//i为每次循环计数变量,x为人员序号,K为剩余人数
while(k!=0)
{
x++
if(x>n) x=1//当人员到达数组尾,序号重设为1
if(a[x])i++ // 跳过已退出人员
if(i==m)
{a[x]=falsei=0k--}//当数到m时,退出人员设为false,剩余人数减1,i设为0,重新计数
}
cout<<"留下来的人序号为: "<<x<<"\n"
delete [] a
cin.get()
cin.get()//等待下一次键击关闭窗口
return 0
}
法二(递归法):
此题可用数学方法求解。
设有n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数 (用数学方法解的时候需要注意应当从0开始编号,因为取余会取到0解。)
实质是一个递推,n个人中最终留下来的序号与n-1个人中留下来的人的序号有一个递推关系式。
假设除去第k个人,则
0, 1, 2, 3, ..., k-2, k-1, k, ..., n-1 // 原始序列 (1)
0, 1, 2, 3, ..., k-2, , k, ..., n-1 // 除去第k人,即除去序号为k-1的人 (2)
k, k+1, ..., n-1, 0, 1, ..., k-2// 以序号k为起始,从k开始报0 (3)
0, 1, ..., n-k-1, n-k, n-k+1, ..., n-2 // 作编号转换,此时队列为n-1人 (4)
变换后就完完全全成为了(n-1)个人报数的子问题,注意(1)式和(4)式,是同一个问题,不同的仅仅是人数。比较(4)和(3),不难看出,0+k=k, 1+k=k+1, ... ,(3)式中'0'后面的数字,
((n-3)+k)%n=k-3,((n-2)+k)%n=k-2, 对于(3)式中'0'前面的数字,由于比n小,也可看作(0+k)%n=k, (1+k)%n=k+1, 故可得出规律:
设(3)中某一数为x' , (4)中对应的数为x,则有:x'=(x+k)%n.
设x为最终留下的人序号时,队列只剩下1人时,显然x=0此时可向前回溯至2人时x对应的序号,3人时x对应的序号……直至n人时x的序号,即为所求。
#include <iostream>using namespace std
int main()
{
int n,m,f=0
cin>>n>>m
for(int i=2i<=ni++)
f=(f+m)%i
cout<<f+1<<endl
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)