HDU4666 Hyperspace(数学推理+数据结构)

                     

问题领悟

1)求两点的曼哈顿距离

2)求n个点中最大的曼哈顿距离(朴素算法:O(n^2) )  [在不考虑删除操作的情况下]

3)加入删除操作,如果前面已求得的最大距离若有一个被删去,则需要重新计算最大曼哈顿距离,最坏情况时间复杂度可达O(n^3) ;远远超出。

问题思考

1)首先能不能找到问题的一种朴素算法,使复杂度为O(n^2)的,在10s时间下可以试试;

2)期待这类O(n^2)问题的更高效的算法!

   A.思考方向1:可能要用数据结构优化到Onlg(n));

3)不存在,那就考虑问题本身具有的特殊性,或挖掘出问题本身的性质和规律:

   曼哈顿距离:|x1-x2| + |y1-y2|

   求最大值。

   怎么考察此式的性质?

   

   将式拆分,重组,得:

   

   我们可以发现一个规律点:即不同点相对应的维数必然符号相反,如同一个式中,xi必然对应着-yi,由此将后面式子负号提出,用01二进制每个点内部各维数间的正负号,得到对应两个相同符号的式子相减的表达式,如对于二维(xi,xj,(yi,yj) ,用二维数组 A[N][2^k] 保存N*(2^k)个数据可分解如下:

|xi-yi| + |xj-yj|=

max{

   A[1][0]-A[2][0]

   A[1][1]-A[2][1]

   A[1][2]-A[2][2]

   A[1][3]-A[2][3]

}

所以对于2^k中每一个数(即表示单个点内个位数间的运算符号),运算后保存在方便查找最值且下标为K的数据结构中(如堆,优先队列,multiset集合等),遍历2^k种情况,最大最小值,相减找出最大差值即可:

 

源程序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set> 
using namespace std;
#define maxn 60005
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)

multiset<int> mset[1<<5];
int arr[maxn][6];

int main()
{	
	int q,k,i,j,l,op,ith,sum,ma;
	while(~scanf("%d%d",&q,&k))
	{
		for(i=0;i<(1<<k);i++)
		    mset[i].clear();          //注意容器的初始化清空! 
		
		for(i=1;i<=q;i++)
		{
			scanf("%d",&op);
			if(!op)
			{
				for(j=0;j<k;j++)
					scanf("%d",&arr[i][j]);
				for(j=0;j<(1<<k);j++)
				{
					sum=0;
					for(l=0;l<k;l++)
					{
						if(j&(1<<l))
							sum+=arr[i][l];
						else
						    sum-=arr[i][l];
					}
					mset[j].insert(sum);	
				}
			}
			else
			{
				scanf("%d",&ith);
				for(j=0;j<(1<<k);j++)
				{
					sum=0;
					for(l=0;l<k;l++)
					{
						if(j&(1<<l))
							sum+=arr[ith][l];
						else
						    sum-=arr[ith][l];
					}
					multiset<int>::iterator it;
					it=mset[j].find(sum);
					mset[j].erase(it);	
				}
			}
			
			ma=0;
			multiset<int>::iterator it1,it2;
			for(j=0;j<(1<<k);j++)
			{
				it1=mset[j].begin();
				it2=mset[j].end();
				it2--;  
				ma=Max(ma,*it2-*it1);
			}
			
			printf("%d\n",ma);
		}
	}
	return 0;
}


 

   

   

转载于:https://www.cnblogs.com/litaotao/p/3592453.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值