2018.5.27(hdu1276 士兵队列训练问题)

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;
}

https://blog.csdn.net/dxx_111/article/details/47208733

猜你喜欢

转载自blog.csdn.net/violet_ljp/article/details/80467203