http://acm.hdu.edu.cn/showproblem.php?pid=1276
先上AC代码,解析稍后献上~~~~
解析:
利用链表记录士兵的顺序,每次循环删除满足条件的结点;
假设n=20,其初始编号为①~⑳;
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
第一轮报数为1,2报数,报到2的士兵出列,易知出列的士兵为2,4,6,8,10,12,14,16,18,20,由于每次出列,都会删除需要出列的士兵,模拟一下程序:
第一个出列的士兵为2,在②位置,删除后,剩余队列为1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;第二个出列的士兵为4,其新编号为③,删除后,剩余队列为1,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20接着按着上述进行操作,发现出队的编号依次为②③④⑤⑥⑦⑧⑨⑩⑪,共出队n/2=10位士兵,故当flag==0时(flag用于判读1,2还是1,2,3报数),删除结点的循环为:
for(int i=2,k=1;k<=soldier/2;i++,k++)//依次删除报2的结点,共出队k位士兵
head=Delete(head,i);
第一轮出队操作后,进入1,2,3报号出队,报3的士兵出队,此时剩余士兵位1,3,5,7,9,11,13,15,17,19;按照上述分析方式,报3的士兵出列,则此轮出列士兵的初始值为5,11,17,其新编号依次为③⑤⑦,依次比前一个出列的士兵编号+2,故当flag==1时,删除结点的循环为:
for(int i=3,k=1;k<=soldier/3;i+=2,k++)//依次删除报3的结点,出队士兵宗人数为k人;
head=Delete(head,i);
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct Soldier
{
int initial_number;//记录某个结点士兵的初始值;
Soldier *next;
};
Soldier *Create(int soldier)
{
Soldier *head=NULL,*tail=NULL;
Soldier *new_point;
for(int i=1;i<=soldier;++i)
{
new_point=(Soldier*)malloc(sizeof(Soldier));
new_point->initial_number=i;
new_point->next=NULL;
if(head==NULL)
head=new_point;
else
tail->next=new_point;
tail=new_point;
}
return head;
}
Soldier *Delete(Soldier *head,int x)//删除head链表中第x位的结点
{
Soldier *current_point;
Soldier *delete_point=head;
int i=1;
while(i<x)
{
i++;
current_point=delete_point;
delete_point=delete_point->next;
}
current_point->next=delete_point->next;
free(delete_point);
return head;
}
Soldier *Solve(Soldier *head,int soldier,bool flag)//soldier变量用来记录当前士兵剩余总人数;flag用来判断是按1,2报数,还是1,2,3报数;
{
if(soldier<=3)//当当前剩余人数剩余不超过3时,递归结束
return head;
Soldier *current_point=head;
if(flag==0)//如果flag==0,这是按1,2报数
{
for(int i=2,k=1;k<=soldier/2;i++,k++)//依次删除报2的结点
head=Delete(head,i);
soldier-=soldier/2;//更新soldier,flag的值
Solve(head,soldier,!flag);//递归调用
}
else
{
for(int i=3,k=1;k<=soldier/3;i+=2,k++)//依次删除报3的结点
head=Delete(head,i);
soldier-=soldier/3;//更新soldier,flag的值
Solve(head,soldier,!flag);//递归调用
}
}
void print(Soldier *head)//打印结果
{
for(Soldier *p=head;p!=NULL;p=p->next)
{
if(p==head)
printf("%d",p->initial_number);
else
printf(" %d",p->initial_number);
}
printf("\n");
}
int main()
{
int N;
cin>>N;
while(N--)
{
int soldier;
Soldier *head;
cin>>soldier;
head=Create(soldier);//创建链表
head=Solve(head,soldier,0);
print(head);
}
return 0;
}