解法1:暴力解法
#include <iostream>
using namespace std;
int main()
{
int n, m;
m=2;
scanf("%d", &n);
bool vis[n];
int t = 0, tot = n;
while(tot > 0)//人数
{
int cnt = 0;
while(1)
{
t++;
if(t > n) t %= n;
if(!vis[t]) cnt++;
//printf("%d %d\n", vis[t], t);
if(cnt == m) break;//数到m
}
//printf("%d\n", t);
vis[t] = 1;
tot--;
}
printf("%d\n", t);
return 0;
}
解法2:使用数组解决
#include <stdio.h>
int main()
{
//参数: n(人数),m(第m个人死),last(剩余的人数)
int i,j,n,m,last;
int tag[100];
printf("输入参加的人数:\n");
scanf("%d",&n);
printf("输入每隔多少死一个人:\n");
scanf("%d",&m);
printf("\n准备报数!\n\n");
//初始化数组
for(i = 0;i < n;i++)
{
tag[i] = 1;
}
//开始报数
j = 1;
last = n;
for(i = 0;last > 1;i++)
{
if(!tag[i%n])continue;
if(j == m)
{
j = 1;
tag[i%n] = 0;
printf("第%d个人自杀了,大家快鼓掌!啪啪啪!\n",(i%n)+1);
last--;
}
else j++;
}
for(i = 0;i < n;i++)if(tag[i])break;
printf("第%d个人活下来了!\n",i+1);
return 0;
}
解法3:使用链表解决
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct node
{
int data;
node *next;
};
void out(node *&p1,node *&p2)
{
p1->next = p2->next;
free(p2);
}
node *Find(int k,node *p)
{
int count = 0;
node *p1,*p2;
p1 = p;
p2 = p->next;
while(p2 != p1)
{
count++;
if(count == k)
{
out(p1,p2);
count = 0;
p2 = p1->next;
}
else
{
p1 = p1->next;
p2 = p2->next;
}
}
return p2;
}
void get(node *&p)
{
p = (node *)malloc(sizeof(node));
p->next = NULL;
}
int main()
{
node *p1,*p2,*s1,*s2;
get(p1);
s1 = p1;
int n,k = 2;
cin>>n;
for(int i = 1;i <= n;i++)
{
get(p2);
p1->next = p2;
p2->data = i;
p1 = p2;
}
p1->next = s1->next;
cout<<Find(k,p1)->data<<endl;
}
解法4:使用数学公示
[info] 上面讲述的两种解决约瑟夫问题的方法都是模拟一个报数的流程,对付一些小的数据量 还可以,但是假如我们输入的数据量很大的时候,就会显得很笨重,我们需要使用一些 数学策略来解决这个问题,有这样一个递推公式: f1 =0; f[i]=(f[i-1]+m)%i; (i>1) 而我们根据上面这个递推公式,写出如下代码:
#include <stdio.h>
int main()
{
int n, m, i, s=0;
printf ("N M = ");
scanf("%d%d", &n, &m);
for (i=2; i<=n; i++)s=(s+m)%i;
printf ("最后一个剩下的人: %d\n", s+1);
return 0;
}