WC 2006 species

這是一道很奇怪的題,說它奇怪就是一旦想出來就會覺得自己被侮辱了智商,但想不出來更覺得自己智商低

其實是一個比較奇特的想法。

首先對於|a-b|的絕對值符號特別的“厭惡“,怎麼讓它變得好看呢?注意到題目中的k<=5,那有什麼用呢?原因是k,2^k,k的階乘都很小!!!

那。。。。。又有什麼用?

注意到假設a<=b,則-a-b<a-b<=|a-b|=b-a=(-a)-(-b)

對於任意兩個物種的k個屬性,若用0,1表示屬性值的正負,選擇最小的屬性值減去更新答案就可以了

細節,注意第k號屬性不可以改符號,所以要按第k號屬性排序

複雜度O(n*2^k+nlogn)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
int c[10],a[100005][10],b[100005];
int n=0,m=0;
int cmp(const void *p,const void *q)
{
  return a[*(int *)p][m]-a[*(int *)q][m];
}
int main()
{
  freopen("species.in","r",stdin);
  freopen("species.out","w",stdout);
  int s=0,i=0,j=0,mins=0,minother=0,state=0,ans=0,ansother=0,ansone=0;
  scanf("%d%d",&n,&m);
  for (i=1;i<=m;i++)
    scanf("%d",&c[i]);
  c[m]=-c[m];
  for (i=1;i<=n;i++)
    {
      for (j=1;j<=m;j++)
        scanf("%d",&a[i][j]);
      b[i]=i;
    }
  qsort(b+1,n,sizeof(b[0]),cmp);
  for (state=1<<(m-1);state<=(1<<m)-1;state++)
    {
      for (i=1;i<=n;i++)
        {
          s=0;
          for (j=1;j<=m;j++)
            if (state&(1<<(j-1)))
              s+=c[j]*a[b[i]][j];
            else
              s-=c[j]*a[b[i]][j];
          if (i==1)
            {
              mins=s;
              minother=b[1];
            }
          else
            {
              if (s-mins>ans)
                {
                  ans=s-mins;
                  ansone=b[i];
                  ansother=minother;
                }
              if (s<mins)
                {
                  mins=s;
                  minother=b[i];
                }
            }
        }
    }
  printf("%d %d\n%d",ansone,ansother,ans);
  return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章