這是一道很奇怪的題,說它奇怪就是一旦想出來就會覺得自己被侮辱了智商,但想不出來更覺得自己智商低
其實是一個比較奇特的想法。
首先對於|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;
}