题目
救济金发放n(n≤20)个人站成一圈,逆时针,编号为1~n。有两个官员,A从1开始逆时针数,B从n开始顺时针数。在每一轮中,官员A数k个就停下来,官员B数m个就停下来(有可能两个官员停在同一个人上)。被官员选中的人(1个或2个)离开队伍去领取救济金。输入n,k,m,输出每轮里被选中的人的编号(若有2个人,先输出被A选中的)
解决方法1️⃣
这个跳出递归的方法有待改善。。。
#include <stdio.h>
#include <string.h>
int k,m,a[20],n,flag=0;
void num(int e,int f)
{
int i=0,j=0;
flag=fla(flag);
if(flag)
{
return 0;
}
else
{
for(i=0;i<k;)
{
if(a[(e+i)%n]==0) e++;
else i++;
}
for(j=0;j<m;)
{
if(a[(f-j+n)%n]==0) f--;
else j++;
}
if(a[(e+i-1)%n]==a[(f-j+n+1)%n]) printf("%d ",a[(e+i-1)%n]);
else printf("%d %d ",a[(e+i-1)%n],a[(f-j+n+1)%n]);
a[(e+i-1)%n]=0;
a[(f-j+n+1)%n]=0;
num((e+i-1)%n,(f-j+n+1)%n);
}
}
int fla(int flag)
{
int i;
for(i=0;i<n;i++)
{
if(a[i]!=0)
{
return flag=0;
}
}
return flag=1;
}
void main()
{
int i;
scanf("%d%d%d",&n,&k,&m);
for(i=1;i<=n;i++)
{
a[i-1]=i;
}
num(0,n-1);
}
解决方法2️⃣
目前的最优解(循环调用函数)
#include<stdio.h>
#define maxn 25
int n, k, m, a[maxn];
//逆时针走t步,步长是d(-1表示顺时针走),返回新位置
int go(int p, int d, int t) {
while(t--) {
do { p = (p+d+n-1) % n + 1; } while(a[p] == 0); //走到下一个非0数字
}
return p;
}
void main() {
int i;
scanf("%d%d%d", &n, &k, &m);
for(i = 1; i <= n; i++) a[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(p2 != p1) { printf("%3d", p2); left--; }
a[p1] = a[p2] = 0;
if(left) printf(",");
}
printf("\n");
}
解决方法3️⃣
链表,容易理解,拓展性强
#define NULL 0
#define LEN sizeof(struct stu)
int n;
struct stu
{
int num;
struct stu *breaky;
struct stu *back;
struct stu *next;
};
struct stu *p,*op;
struct stu *create(int n)
{
struct stu *head,*new,*tail;
int count = 1;
while(count<=n)
{
new = (struct stu * ) malloc(LEN);
new->num=count;
if(count==1)
{
head = new; tail=new;
}
else
{
new->back=tail;
tail->next=new; //自左向右结合
tail=new;
}
count++;
}
tail->breaky=NULL;
tail->next=head;
head->back=tail;
return(head);
}
void newlo(int b,int k)
{
struct stu *m,*l;
k--; b--;
while(--k)
{
p=p->next;
}
while(--b)
{
op=op->back;
}
m=p; l=op;
p=p->next;
op=op->back;
printf("%d ",p->num); n--;
if(p->num!=op->num)
{
printf("%d ",op->num); n--;
}
if(p->next==op)
{
m->next=l; l->back=m;
}
else if(op->next==p)
{
op->back->next=p->next; p->next->back=op->back;
}
else
{
m->next=p->next; p->next->back = m;
l->back=op->back; op->back->next = l;
}
}
void main()
{
int k,b;
struct stu *temp;
scanf("%d%d%d",&n,&k,&b);
p = create(n);
temp = p;
while(p->breaky!=NULL)
{
p=p->next;
}
op=p;
p=temp;
while(n)
{
newlo(b,k);
if(p->next==op)
{
p=p->next;
op=op->back;
}
p=p->next;
op=op->back;
}
}
拓展
只需要逆时针数数(链表很简单)
#define NULL 0
#define LEN sizeof(struct stu)
struct stu
{
int num;
struct stu *breaky;
struct stu *back;
struct stu *next;
};
struct stu *p;
int flag=0;
struct stu *create(int n) //只考虑逆时针的话可以把back去掉并且不需要breaky
{
struct stu *head,*new,*tail;
int count = 1;
while(count<=n)
{
new = (struct stu * ) malloc(LEN);
new->num=count;
if(count==1)
{
head = new; tail=new;
}
else
{
new->back=tail;
tail->next=new; //自左向右结合
tail=new;
}
count++;
}
tail->breaky=NULL;
tail->next=head;
head->back=tail;
return(head);
}
void *newlo(int k)
{
struct stu *m;
k--;
while(--k)
{
p=p->next;
}
m=p;
p=p->next;
printf("%d ",p->num);
m->next=p->next;
if(p==m)
{
flag=1;
}
}
void main()
{
int n,k,b;
//struct stu *temp;
scanf("%d%d%d",&n,&k,&b);
p = create(n);
//temp = p;
/*while(p->breaky!=NULL)
{
p=p->next;
}
op=p;*/
//p=temp;
while(!flag)
{
newlo(k);
/*if(p->next==op)
{
p=p->next;
op=op->back;
}*/
p=p->next;
//op=op->back;
}
}
只需要顺时针数数(链表很简单)
#define NULL 0
#define LEN sizeof(struct stu)
struct stu
{
int num;
struct stu *breaky;
struct stu *back;
struct stu *next;
};
struct stu *p,*op;
int flag=0;
struct stu *create(int n)
{
struct stu *head,*new,*tail;
int count = 1;
while(count<=n)
{
new = (struct stu * ) malloc(LEN);
new->num=count;
if(count==1)
{
head = new; tail=new;
}
else
{
new->back=tail;
tail->next=new; //自左向右结合
tail=new;
}
count++;
}
tail->breaky=NULL;
tail->next=head;
head->back=tail;
return(head);
}
void newlo(int b)
{
struct stu *l;
b--;
while(--b)
{
op=op->back;
}
l=op;
op=op->back;
printf("%d ",op->num);
l->back=op->back;
if(op==l)
{
flag=1;
}
}
void main()
{
int n,k,b;
struct stu *temp;
scanf("%d%d%d",&n,&k,&b);
p = create(n);
temp = p;
while(p->breaky!=NULL)
{
p=p->next;
}
op=p;
p=temp;
while(!flag)
{
newlo(b);
/*if(p->next==op)
{
p=p->next;
op=op->back;
}*/
//p=p->next;
op=op->back;
}
}