1.约瑟夫环问题 原题:
n个人想玩残酷的死亡游戏,游戏规则如下: n个人进行编号,分别从1到n,排成一个圈,
顺时针从1开始数到m,数到m的人被杀,剩下的人继续游戏,活到最后的一个人是胜利者。
请输出最后一个人的编号。
#include <cstdio>
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int s=0;
for (int i=2; i<=n; i++)
{
s=(s+m)%i;//求最后剩下的人的递推公式
}
printf("%d\n",s+1);
}
return 0;
}
2.约瑟夫环问题变形 变为一开始从第s个人开始报数,报1
从第n个人围坐一圈,并按顺时针方向1—n编号。从第s个人开始进行报数,报数到第m个人,此人出圈,
再从他的下一个人重新开始从1到m的报数进行下去 ,直到只剩一个人为业
人数n
从第s个人开始报数1
报到第几个数m
#include <cstdio>
#include <iostream>
using namespace std;
int f[100];
int main()
{
int n,m,t;
while(scanf("%d%d%d",&n,&t,&m)!=EOF)
{
int s=0;
int k=1;
for(int i=t;i<=n;i++)
f[k++]=i;
for(int i=1;i<t;i++)
f[k++]=i;
for (int i=2; i<=n; i++)
{
s=(s+m)%i;
}
printf("%d\n",f[s+1]);
}
return 0;
}
3.hdu1443 约瑟夫环问题变形
输入k 前k个好人后k个坏人,总共2k个人 求最小的m使最后一个坏人死前好人一个不死 由于前k个人都不死,
所以前k的人位置号码不会发生变动,因此(s+1)的位置<k不成立
数据很小只有14 ,暴力枚举加递推公式
#include <iostream>
#include <cstring>
using namespace std;
int k,a[30],ans[15];
int main()
{
for(int i=1;i<14;i++)
{
int m=1;
memset(a,0,sizeof(a));
int n=2*i;
for(int j=1;j<=i;j++)
{
a[j]=(a[j-1]+m-1)%(n-j+1);
if(a[j]<i)
{
m++;
j=0;
}
}
ans[i]=m;
}
while(cin>>k&&k)
cout<<ans[k]<<endl;
return 0;
}
或者用while
while(1)
{
s=(s+m-1)%n;
n--;
// if(s+1<=i) break;循环结束条件
//if(n==i) { flag=1; break;}
}
4.序号从0-n-1
第一个递归是求最后活下来的人的序号
int s=0;
for (int i=2; i<=n; i++)
{
s=(s+m)%i;//求最后剩下的人的递推公式
}
第二个递归是每一次死掉的人的位置,不是序号(int s=0)
while(1)
{
s=(s+m-1)%n;
n--;
}
5.poj3750 小孩数数问题
前几个问题集合
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
char name1[65][15],name2[65][15];
int n,w,s,t;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
{
cin>>name1[i];
}
scanf("%d,%d",&w,&s);//用scanf输入
int k=0;
for(int i=w; i<=n; i++)
strcpy(name2[k++],name1[i]);
for(int i=1; i<w; i++)
strcpy(name2[k++],name1[i]);
t=0;
while(1)
{
t=(t+s-1)%n;//t是位置不是序号,所以每次退出一个人,后面的人把前面的空补上
n--;
cout<<name2[t]<<endl;
int k=n-t,T=t;
while(k--)
{
strcpy(name2[T],name2[T+1]);
T++;
}
if(n==0)break;
}
}
return 0;
}
或者直接模拟