根据题目要求,如果对任意两个物品属性进行比对计算,复杂度为。为满足时空要求,需要考虑只比对那些可能是完美对的物品。
采用链式哈希法对物品进行分组,组内两两比对即可。哈希法的效率取决于分组的数量,同时也与原始数据相关。因此如果某些数据无法通过时,可以考虑更换哈希函数或对哈希函数进行优化。
如果两个物品是完美对,那么a1+b1==a2+b2,可得a1-a2== -(b1-b2)。也就是说如果一个物品k个值为3 9 11,其中前两个数字差为-6,那么完美对物品的前两个数字的差必须是6。此处哈希函数设定为前两个数字的差(如果用前两个绝对值则可能会超时)。
不超时设计。
#include<bits/stdc++.h>
using namespace std;
int a[100005][11];
int n,k;
vector<int>head[2005];/**< 实现哈希表,哈希值为数组下表,相同哈希值元素保存在同一数组内 */
bool check(int x,int y)/**< 比较a数组第x和第y个元素是否完美对*/
{
int sum=a[x][1]+a[y][1];
for(int i=2; i<=k; i++)
if(a[x][i]+a[y][i]!=sum)
return false;
return true;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int i,j,ans=0;
cin>>n>>k;
for(i=1; i<=n; i++)
for(j=1; j<=k; j++)
cin>>a[i][j];
for(i=1; i<=n; i++)
{
int h=a[i][1]-a[i][k];/**< 计算哈希函数h,可能是负值,用绝对值分组会超时 */
for(j=0; j<head[-h+1000].size(); j++) /**< 只能和h的相反数形成完美对*/
if(check(i,head[-h+1000][j]))
ans++;
head[h+1000].push_back(i);/**< 数组下标不能为负数,所以所有的值存储时做了一个正偏移 */
}
cout<<ans;
return 0;
}
/**< 可能超时的另一种方案 */
// int h=abs(a[i][1]-a[i][k]);/**< 计算哈希函数h */
// for(j=0; j<head[h].size(); j++) /**< 只有h相同才能形成完美对*/
// if(check(i,head[h][j]))
// ans++;
// head[h].push_back(i);