南工ACM:心急的C小加

描述
C小加有一些木棒,它们的长度和质量都已经知道,需要一个机器处理这些木棒,机器开启的时候需要耗费一个单位的时间,如果第i+1个木棒的重量和长度都大于等于第i个处理的木棒,那么将不会耗费时间,否则需要消耗一个单位的时间。因为急着去约会,C小加想在最短的时间内把木棒处理完,你能告诉他应该怎样做吗?

输入
第一行是一个整数T (1<T<1500) ,表示输入数据一共有T组。
每组测试数据的第一行是一个整数N(1<=N<=5000),表示有N个木棒。接下来的一行分别输入N个木棒的L, W0<L,W<=10000 ,用一个空格隔开,分别表示木棒的长度和质量。
输出
处理这些木棒的最短时间。
样例输入
3
5
4 9 5 2 2 1 3 5 1 4
3
2 2 1 1 2 2
3
1 3 2 2 3 1
样例输出
2
1
3

思路:
a[i]包括3个属性,长度l,宽度w,和 flag(0表示未被访问过,1表示已经访问过)
先按照长度将木棍a[1~n]进行从小到大的排序。
之后,一开始的想法是,排完序之后,再走以下步骤:
1. num=0 ; left=1 ; right = N;
2. 从所有[left , right ]范围内的所有a[i].flag==0的木棍中,选择w最小的木棍
3. 将这个木棍a[i].flag=1 , num++;
4. 令left=i+1 ,重复2 ,做到到顶,再继续第5步
5. 从i=1开始遍历,寻找第一个a[i].flag==0的那个i ,令left=i ,重复第2步。直到所有的元素的flag都为1。

int main()
{
      对a.l进行排序;

     while(还有a[i].flag==0)
     {
         从i=1开始遍历,寻找第一个a[i].flag==0的那个i ,令left=i;
         num++; 
        for(i<=N) 
        {
            从所有[left , right ]范围内的所有a[i].flag==0的木棍中,选择w最小的木棍;
            a[i].flag=1 ;

              left=i+1;
        }
     }
     print(num) ;
}

这个过程,写起来太复杂,提过后, 直接显示超时了。

于是就去寻找别人的代码,发现,其实根本就不比一定要从最小的开始。
从1开始选择第一个a.flag==0的a[i]。从他开始,发现后面第一个比他的w大的元素就行,不必是最小的。
1. 对a.L进行排序. 令num=0; s=1;
2. 从i=1开始选择第一个a[i].flag==0的a[i]。如果所有的flag==1,结束循环,否则进行步骤3
3. num++ ; b=i ; j=i+1;
4. 如果s[j].w>=s[b].w 且 s[j].flag=0, 那么令s[j].flag=1 , b=j ; j++;否则 只有 j++; 不断重复第4步,直到j>=N
5. 步骤4结束后,调到第2步循环

int main()
{
      对a.l进行排序;

     while(还有a[i].flag==0)
     {
         从i=1开始遍历,寻找第一个a[i].flag==0的那个i ,令left=i;
         num++; 
         j=i+1;
         s=i;
        for(j<=N) 
        {
            从i 开始找到第一个 j 有a[i].flag==0a[j].w>a[i].w
            a[j].flag=1 ;
             s=j;
             j++;

        }
     }
     print(num) ;
}
  1. c++排序确实方便
  2. 即使a.L是有序的,但是当L相同时,这时就要求具有相同L的元素,他们的w也是有序的。这就是为什么,有的人说,对L排序AC了,但是对W排序就出错的原因。但是用c语言快排时不能够一次实现的。而在c++中,直接sort(… , … , CMP).再写个简单的CMP函数就完了
    参考博客 :http://blog.csdn.net/u013806814/article/details/38827077

#include<stdio.h>
#include<malloc.h>

struct data{
    int l;
    int w;
    int flag;  //0表示未被访问,1表示已经访问
};

void kuaipai(struct data* a,int l,int r);
int smallest(struct data* a,int l,int r);
void kuaipai2(int* a,int l,int r);
int main()
{
    int T=0,N=0;
    int i=0,j=0,k=0,s=0;
    int L=0,W=0;
    int num=0;
    int b=1,c=1;
    int* r=0;
    struct data* a=0;
    scanf("%d",&T);
    for(i=1;i<=T;i++)
    {
        scanf("%d",&N);
        a=(struct data*)malloc(sizeof(struct data)*(N+1));
        r=(int*)malloc(sizeof(int)*(N+1));
        for(j=1;j<=N;j++)
        {
            scanf("%d%d",&a[j].l,&a[j].w);
            a[j].flag=0;
        }
        kuaipai(a,1,N);//按照a[i].l从大到小排序 

        //for(j=1;j<=N;j++)
    //  {
    //      printf("%d  %d  %d\n",a[j].l,a[j].w,a[j].flag);
    //  }
        b=1;
        r[b]=a[b].w;
        r[0]=1;
        c=2;
        for(j=2;j<=N;j++)
        {
            if(a[j].l==a[b].l)
            {
                r[c]=a[j].w;
                c++;
                r[0]++;
                if(j!=N)
                {
                    continue;
                }

            }
            kuaipai2(r,1,r[0]);

            for(c=1;c<=r[0];c++)
            {
                a[b+c-1].w=r[c];
            //  printf("%d\n",a[b+c-1].w);
            }
            b=j;
            c=1;
            r[c]=a[b].w;
            c++;
            r[0]=1;
        }

        //for(j=1;j<=N;j++)
        //{
        //  printf("%d  %d  %d\n",a[j].l,a[j].w,a[j].flag);
    //  }
        a[0].flag=N;
        num=1;
        while(1)
        {
            for(k=1;k<=N;k++)
            {
                if(a[k].flag==0)
                {
                    a[k].flag=1;
                //  printf("%d  %d  %d\n",a[k].l,a[k].w,a[k].flag);
                    num++;
                    break;
                }
            }

            if(k>=N)
            {
                break;
            }


            s=k;
            for(k=k+1;k<=N;k++)
            {
                if(a[k].flag==0 && a[k].w>=a[s].w) 
                {
                    a[k].flag=1;
            //      printf("%d  %d  %d\n",a[k].l,a[k].w,a[k].flag);
                    s=k;
                }
            }

        }
        printf("%d\n",num-1);
    }

    return 0;
}

void kuaipai(struct data* a,int l,int r)
{
    int i=l,j=l;
    int k=a[r].l;
    int x=0,y=0;
    if(l>=r)
        return;

    for(i=l;i<=r-1;i++)
    {
        if(a[i].l<k)
        {
            x=a[i].l;
            y=a[i].w;

            a[i].l=a[j].l;
            a[i].w=a[j].w;

            a[j].l=x;
            a[j].w=y;

            j++;
        }
    }

    x=a[r].l;
    y=a[r].w;

    a[r].l=a[j].l;
    a[r].w=a[j].w;

    a[j].l=x;
    a[j].w=y;

    kuaipai(a,l,j-1);
    kuaipai(a,j+1,r);

    return;
}

void kuaipai2(int* a,int l,int r)
{
    int i=l,j=l;
    int k=a[r];
    int y=0;
    if(l>=r)
        return;

    for(i=l;i<=r-1;i++)
    {
        if(a[i]<k)
        {

            y=a[i];


            a[i]=a[j];


            a[j]=y;

            j++;
        }
    }


    y=a[r];


    a[r]=a[j];


    a[j]=y;

    kuaipai2(a,l,j-1);
    kuaipai2(a,j+1,r);

    return;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值