您的位置:首页 > 其它

杭电2211杀人游戏

2014-04-17 19:29 323 查看
其实此题在测试数据小的情况下可以用解决约瑟夫环的方法

但是因为此题数据很大(2^31),所以用解约瑟夫的方法肯定会爆内存
解题的关键在于找出每次操作前后编号位置的变化关系

-----------------------------------------------------------------------------------------------------------------------------------------

采用递归的思路,任取一轮开始讨论,假设此时剩下m人

1,2,3,4,5......m

我们需要推出上一次第m个人的位置,由于是每第k个就杀掉,所以要还原上一次的队列就必须每两k-1个人就要补上1个人,

当前第m人前面有m-1人,所以要补上(m-1)/(k-1)个人,因此当前第m人在上一次队列中的位置是(m-1)/(k-1)+m

至此,关系已经推出,接下来是代码实现

#include<stdio.h>
int main()
{
int  dfs(int n,int k);
int T;
int n,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
printf("%d\n",dfs(n,k));
}
return 0;
}
int dfs(int n,int k)
{
int num;
if(n==k)
{
return k;
}
num=dfs(n-n/k,k);
return ((num-1)/(k-1)+num);
}


-------------------------------------------------------------------------------------------------------------------------------------------

做此题时无意间想出的用数组解决约瑟夫环的方法(之前只学过链表的),不知道是不是很普遍的,

主要是利用两个数组交替存放剩下的队列,在此贴出来水水

#include<stdio.h>
#include<stdlib.h>
int a[100000000];
int b[100000000];
int main()
{
void kkk(int a[1],int b[],int na,int k);
int T,n,k;
scanf("%d",&T);
int i,j,na,nb;
while(T--)
{
scanf("%d%d",&n,&k);
for(i=1;i<=n;++i)
{
a[i]=b[i]=i;
}
kkk(a,b,n,k);
}
return 0;
}
void kkk(int a[],int b[],int na,int k)
{
int nb=1;
int i;
for(i=1;i<=na;++i)
{
if(i%k!=0)
{b[nb]=a[i];nb++;}
}
nb--;
if(nb==k)
{
printf("%d\n",b[k]);
return;
}
else
{
kkk(b,a,nb,k);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  杭电