题意:
有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),
后k个为坏人(编号k+1~2k).现在有一个报数m,从编号为1的人开始报数,
报到m的人就要自动死去。问当m为什么值时,
可以使得在出现好人死亡之前,k个坏人先全部死掉?
算法:模拟,从k+1枚举。
ps:约瑟夫问题公式
(1)令f[i]表示i(0~i-1)个人,报m,最后胜利者的编号,
递推公式 f[1]=0; f[i]=(f[i-1]+m)%i; (i>1)
(2)有n个人(0,...,n-1),数m,
则第i轮出局的人为f(i)=(f(i-1)+m-1)%(n-i+1),f(0)=0;
#include <iostream>
#include <cstdio>#include <cstring>
using namespace std;
int man[40],j[20];//j记录算出的值,防止重复计算超时
int kill(int n,int start,int num)
{
int i=start-1,sum=0;
if (i==0) i=n; //环链注意首尾相连
while (sum!=num)
{
i++;
if (i==n+1) i=1;
if (man[i]==1) sum++;
}
return i;
}
int main()
{
int k,n,m,flag,i;
freopen("in.txt","r",stdin);
while (cin>>k)
{
if (k==0) break;
n=2*k;
flag=0;
m=k;
while (!flag&&j[k]==0)
{
int start=1,alive=n,dead;
for (i=1;i<=n;i++) man[i]=1;
m++;
flag=1;
for (i=1;i<=k&&flag==1;i++)
{
int num;
if (m%alive>0) num=m%alive;else num=alive;//m%alive==0 时的处理
dead=kill(n,start,num);
if (dead<=k&&dead>0) flag=0;
else
{
man[dead]=0;
alive--;
start=dead+1;
if (start==n+1) start=1;
}
}
}
if (j[k]==0) j[k]=m;
cout<<j[k]<<endl;
}
return 0;
}