救济金发放

来源:互联网 发布:eda软件是什么 编辑:程序博客网 时间:2024/04/28 08:02

n(n<20)个人站成一圈,逆时针编号为1~n。有两个官员,A从1开始逆时针数,B从n开始顺时针数。在每一轮中官员A数k个就停下来,官员B数m个就停下来(注意,有可能两个官员停在同一个人上)。接下来,被考官选中的人(1个或者2个)离开队伍。

输入:n,k,m

输出:每轮被选中的人的编号(如果有两个人,先输出被A选中的)。

如:n=10,k=4,m=3,shcuhu 4,8,9,5,3,1,2,6,10,7。注意,输出的每个数应当恰好占3列。

【分析】

题目难度不是很大,主要是循环访问数组的问题,使用取模(%)就可以实现,但是题目中有陷阱。需要注意。

#include<iostream>using namespace std;const int Size=22;int man[Size];int main(){int n,k,m;int left,p1,pn;cin>>n>>k>>m;for(int i=1;i<=n;i++)man[i]=i;man[0]=n;left=n;p1=1;pn=n;while(left){for(int i=p1,j=1;j<=k;i++){if(man[i%n]!=0)j++;if(j==k+1){p1=man[i%n];man[i%n]=0;break;}}for(int j=pn,i=1;i<=m;j--){if(man[j%n]!=0)i++;if(i==m+1){pn=man[j%n];man[j%n]=0;break;}if(j==1)j=n+1;}cout<<p1<<endl;left--;if(p1%n!=pn%n){left--;cout<<pn<<endl;}}return 0;} 

运行结果:


        可以发现和题目给出的参考答案不一样,然后自己把10从前往后4个一起,从后往前3个一起带进去算了一遍,没发现我的算法有啥问题。后面看了课本上的源代码,发现了一点不同,每次我是在找到了m或者K个人的时候就直接给他赋值为0了,但是课本上的代码是把m和k都找出来,最后才赋值为0,;感觉好像都有道理,再仔细读了一遍题目,发现题目中的“接下来,被考官选中的人(1个或者2个)离开队伍”,这句话表明,他们并不是被数到就直接出来,而是先停着,两个都数完了才出来。很遗憾,我的代码有问题。

【修改后】

#include<iostream>#include<cstring>using namespace std;const int Size=22;int man[Size];int main(){int n=10,k=4,m=3;int left,p1,pn;cin>>n>>k>>m;memset(man,0,sizeof(man));for(int i=1;i<n;i++)man[i]=i;man[0]=n;left=n;p1=1;pn=n;while(left){int i,j;for(i=p1,j=1;j<=k;i++){if(man[i%n]!=0)j++;if(j==k+1){p1=i;//man[i%n]=0;break;}}for(j=pn,i=1;i<=m;j--){if(man[j%n]!=0)i++;if(i==m+1){pn=j;//man[j%n]=0;break;}if(j==1)j=n+1;}cout<<man[p1%n]<<endl;left--;if(p1%n!=pn%n){left--;cout<<man[pn%n]<<endl;}man[p1%n]=0;man[pn%n]=0;}return 0;} 
【运行结果】

        不过我们可以从代码中看到,其实在数数的时候两个是一样的,只是一个是递增一个是递减。然后看了课本上的源代码,课本中的处理方式确实比我给出的代码更加巧妙,我给出的代码再最后比较的时候还需要和n取余,才能比较,而且是在最后强制赋值让变量形成一个圈的,但是课本上的处理方法更好懂,除了函数go中的表达式,p=(p+d+n-1)%n+1,这是整个代码中的亮点,但是也是难点。在没有接触回环访问的时候很难想到使用初始值与步长结合,然后还加上n使得无论p之前是什么,经过这一次带换之后,都会落在0-n-1之中,最后的+1用的也很巧妙,一下子就屏蔽了0和n的问题。

【课本代码】

#include<iostream>const int Size=25;int man[Size];int go(int init,int step,int count);int n,k,m;int main(){while(scanf("%d%d%d",&n,&k,&m)==3&&n){for(int i=1;i<=n;i++)man[i]=i;int left=n;int p1=n,p2=1;while(left){p1=go(p1,1,k);p2=go(p2,-1,m);printf("%3d",p1);left--;if(p1!=p2){printf(",%3d",p2);left--;}man[p1]=man[p2]=0;if(left)printf(",");}printf("\n");}return 0;}int go(int init,int step,int count){while(count--){do{init=(init+step+n-1)%n+1;}while(man[init]==0);}return init;}



【运行结果】








0 0
原创粉丝点击