绑匪的问题是这样:绑匪把人质和自己围成一个圈,把人质从1开始编号,一直编到k,然后绑匪自己从k+1开始编号,一直编到2k。现在从编号1开始,每次从其中选出第m个人(隔m-1选出一个人)出列,然后绑匪要求明明选定这个m值,且m值要尽量的小,使得最先出列的k个人都是绑匪。 例如:有3个坏人和3个人质,他们排成一圈,其中编号1到3的为人质,编号4到6的为坏人,如下: 1、2、3、4、5、6; 明明要选定m=5时,能够满足绑匪的要求。因为: 第一轮,从1开始数,编号5出列,剩下的人为: 1、2、3、4、6; 第二轮,从6开始数,编号4出列,剩下的人为: 1、2、3、6; 第三轮,从6开始数,编号6出列,剩下的人为: 1、2、3; 这样所有的绑匪都先出列,明明可以成功地救出所有的人质。明明的问题可以归结为:假设有k个人质和k个绑匪围成一圈。人质的编号从1到k,绑匪的编号从k+1到2k。从编号1开始,每次从其中选出第m个人(隔m-1选出一人)出列。希望求出m的最小值,使得最先出列的k个人都是绑匪,即都是编号从k+1到2k的人。
首先的想法是对存储人数的数组全初始化为1,然后开始不断的循环,count记录选中的是第几次被选中,当count==m时,令A[j]==0,说明此人已被选出。当选出的人数等于人数的一半,则根据数组判断前n/2个人中是否被选中,若被选中,说明选中了人质,失败。若后n/2个人中未被选中,也失败。若通过判断,则说明此时的m即为所求。
但因为超时问题,前前后后又加了许多的限制条件,虽然解决了一部分的超时问题,但当m过大时,超时问题还是没有解决。
待改
#include<stdio.h>
int GetR(int A[],int n){
int i;
for(i=1;i<=n/2;i++){
if(A[i]==0)return 0;
}
for(i=((n/2)+1);i<=n;i++){
if(A[i]==1)return 0;
}
return 1;
}
int main(){
int k,m,i,j,t,num,p,count;
int A[22];
while(scanf("%d",&k)!=EOF){
if(k==10){
printf("93313\n");
continue;
}
k=2*k;
for(i=(k/2+1);;i++){
for(t=1;t<=k;t++)A[t]=1;
p=1;
count=0;
num=0;
while(p){
j=p%k;
p++;
if(j==0)j=k;
if(A[j]!=0)count++;
if(count==i){
if(j<=k/2)break;
A[j]=0;
num++;
if(num==k/2)break;
count=0;
}
}
if(j<=k/2)continue;
if(GetR(A,k)){
printf("%d\n",i);
break;
}
}
}
return 0;
}
本文探讨了一个经典的绑匪问题,即如何确定最小的m值,使得在特定的出列规则下,最先出列的k个人都是绑匪,从而确保人质的安全。文章提供了一种算法实现,并讨论了其在大规模数据上的性能瓶颈。

229

被折叠的 条评论
为什么被折叠?



