[纠结了一天的题目= =]团结的队伍

【描述】

有n个人,需要组成一个“冲金”队,来应付今年的noi,冲金的人数需要越多越好,但当然,需要满足一定的条件。对每个人有两个描述:h身高,w体重。我们定义一个函数Fi=A*(Hi-h) + B*(Wi-w),其中Hi,Wi表示第i个人的身高和体重,h,w表示选中队伍中的最小身高和最小体重,A,B为给出的常数。现在,学校领导的要求是找到一个队伍,满足所有队伍中的人的fi值均不超过C,并且在这个条件上找到队伍最大可能的人数。

【输入格式】

第一行一个数N

第二行三个数A,B,C

接下来N行,每行两个数Hi,Wi

【输出格式】

仅一行,为队伍最大可能的人数。

【样例输入】

8

 1 2 4

 5 1

 3 2

 2 3

2 1

7 2

6 4

5 1

4 3

【样例输出】

5

【数据范围】

N<=1000; A,B,C<=10000; Hi,Wi<=100000;

【分析】

预处理he[i]为a*h[i]+b*w[i]。

首先我们将所有的人按照h进行排序,然后从n到1枚举h最小的那个人。因为当前枚举的i的h在i~n中是最小的,那么包含i的队伍肯定是在i~n中挑选。那么我们要做的就是看用哪个人的w[i]最为最小的w。要注意我们的i是必须要取的,所以我们将i~n按照w排序,那么最为w的那个人的w值肯定要比i的小。那么我们只需要枚举比w[i]小的人即可。因为最小的h是确定的(h[i]),我们可以先算出来一个he1表示he-a*h,然后枚举w值不超过i的人,将he1维护成大根堆,如果最大的满足计算出来的数小于c那么比他小的肯定也满足。需要注意的是,i是必须要的人。那么我们如果发现he1值最大的是i了,当前枚举的是点j,而且函数值已经大于c,那么w值比j小的人肯定也不行。因为如果w比j小的人最为w最小的人存在,那么函数值肯定比j最为最小的人存在的时候大。(说的好混乱)。

然后我们就这么做就行啦!~一个排序,一个堆。

#include <stdio.h>
#define maxn 2010

int h[maxn],w[maxn],he[maxn],w1[maxn],he1[maxn],heep[maxn];
int i,j,k,n,m,s,max,a,b,c,t,top;

void init()
{
     scanf("%d%d%d%d",&n,&a,&b,&c);
     for (i=1;i<=n;++i) scanf("%d%d",&h[i],&w[i]);
}

void swap(int &a,int &b)
{
     int k;
     k=a; a=b; b=k;
}

void sort(int l,int r,int a[],int b[])
{
     int i,j,k;
     i=l; j=r; k=a[(l+r)>>1];
     while (i<j)
     {
           while (a[i]<k) ++i;
           while (a[j]>k) --j;
           if (i<=j)
           {
                    swap(a[i],a[j]);
                    swap(b[i],b[j]);
                    ++i;
                    --j;
           }
     }
     if (l<j) sort(l,j,a,b);
     if (i<r) sort(i,r,a,b);
}

void insert(int p)
{
     heep[++top]=p;
     p=top;
     while ((p>1)&&(he1[heep[p]]>he1[heep[p/2]]))
     {
           swap(heep[p],heep[p/2]);
           p/=2;
     }
}

void dele()
{
     int p;
     heep[1]=heep[top];
     --top;
     p=1;
     while (((p*2<=top)and(he1[heep[p*2]]>he1[heep[p]]))or
              ((p*2+1<=top)and(he1[heep[p*2+1]]>he1[heep[p]])))
     {
          if (p*2+1<=top)
           if (he1[heep[p*2]]>he1[heep[p*2+1]])
            { swap(heep[p],heep[p*2]); p=p*2; } else
            { swap(heep[p],heep[p*2+1]); p=p*2+1; } else
            { swap(heep[p],heep[p*2]); p=p*2; }
         }
}

void work()
{
     sort(1,n,h,w);
     max=0;
     for (i=1;i<=n;++i) he[i]=a*h[i]+b*w[i];
     for (i=n;i>0;--i)
     {
         t=0;
         for (j=n;j>=i;--j)
         {
             w1[++t]=w[j];
             he1[t]=he[j]-a*h[i];
         }
         sort(1,t,w1,he1);
         for (j=t;j>=1;--j) 
             if (w1[j]==w[i])
             {
                             k=j;
                             break;
             }
         s=top=0;
         int tt=0;
         for (j=t;j>=k;--j)
             if (he1[j]-b*w1[k]<=c) insert(j);
         if (top>max) max=top;
         for (j=k-1;j>=1;--j)
         {
             while ((he1[heep[1]]-b*w1[j]>c)&&(top>0))
             {
                   if (heep[1]==t)
                   {
                                  tt=1;
                                  break;
                   }
                   dele();
             }
             if (tt) break;
            if (he1[j]-b*w1[j]<=c) insert(j);
            if (top>max) max=top;
         }
     }
}

int main()
{
    freopen("team.in","r",stdin);
    freopen("team.out","w",stdout);
    
    init();
    work();
    printf("%d\n",max);
    return 0;
}


 

 

posted @ 2010-09-26 19:56  Sephiroth.L.  阅读(310)  评论(0编辑  收藏  举报