K-Dimensional Foil II HihoCoder - 1835 思维+二分

"K-Dimensional Foil" is a dimensional weapon. Its function is quite easy: It can ascend a region in 3D space to K (K≥3) dimension. One can use it to give the enemy unexpected attack. It was called "The Ultimate Weapon".

--"Remembrance of Mars's Past"

You are the chief technology officer in the space fleet, and your fleet was just suffered from the attack of the K-Dimensional Foil. The good news was that you have found the key parameter K, the dimension of the space. But staying in high dimensional space is very dangerous, you must destroy the K-Dimensional Foil as fast as possible.

You have n spaceships, spaceship i locates at si = (si,1, …, si,K), and the K-Dimensional  Foil is a 1-norm ball with center c = (c1, …, cK) and radius r, a 1-norm ball with center c and radius r is a point set defined as
{x |  d(x, c)  ≤ r}, d(x, c) =∑| xi - ci |

In the formula above, the coordinate of point x is (x1, x2 … xK)

Your spaceships will fire laser cannon to destroy the K-Dimensional Foil. The energy decay is very quick with the increase of the distance in the high dimensional space, so for every spaceship, you want to find the closest point (in Euclidean distance) on the K-Dimensional Foil. It's guaranteed that no spaceship is in the K-Dimensional Foil initially.

Input

The first line of the input is an integer T (T ≤ 100), the number of the test cases.

For each test case, the first line contains two integer n, K (1 ≤ n ≤ 50, 1 ≤ K ≤ 100), the number of spaceship in your fleet and the dimension of the space.

Then one line contains an integer r (1 ≤ r ≤ 104 ), the radius of the K-Dimensional Foil.

Then one line contains K integers c1, … cK, meaning the coordinate of the center of the K-Dimensional Foil.

Then n lines follow. Each line contains K integers si,1, …, si,K, meaning the coordinate of a spaceship.

All the absolute values of the coordinate are smaller than 104.

Output

For each test case, output n lines. The ith line contains K numbers representing the coordinate of the closest point on the K-Dimensional Foil to the ith spaceship. The absolute error between your output and the answer should be less than 10-4

Sample Input

1
2 2
1
0 0
1 1
1 3

Sample Output

0.50 0.50
0.00 1.00

Hint

The K-Dimensional Foil in the sample was a square with vertex: (1,0), (0,1), (-1,0), (0,-1)

This problem is special judged.

题意:T组样例,给定n,k,表示有n个点,k维空间。在给定一个r,以及坐标(r1,r2,...,rk)表示圆心,r表示半径(曼哈顿距离),构成一个物体。接下来给定n个点的k维坐标,问这n个点距离这个物体的最短距离是多少。

思路:首先我们把所有坐标平移,使得物体的心在坐标原点上。那么n个点的坐标为(s1-r1,s2-r2,...sk-rk)。我们假设xi=si-ri,

点(x1,x2,...xk)距物体最近的点为(y1,y2,...,yk),那么问题就转化成了这两点之间的距离。我们已知|y1|+|y2|+...+|yk|=r,|x1|+|x2|+....+|xk|=sum。dis^2=(x1-y1)^2+(x2-y2)^2+...+(xk-yk)^2。要使dis最小,我们易知xi与yi同号。

那么dis^2=(|x1|-|y1|)^2+(|x2|-|y2|)^2+...+(|xk|-|yk|)^2。假设ai=xi-yi,那么dis^2=|a1|^2+|a2|^2+...+|ak|^2。我们已知|a1|+|a2|+...+|ak|=sum-r。要使dis最小,如果用贪心的思想,|ai|取(sum-r)/k时最小。但是有一个问题:当|xi|<(sum-r)/k时|ai|不可能取到这个值,因为xi与yi同号。于是问题就转化为了这样一个问题:有水sum-r体积,有n个杯子,每个杯子容积|xi|-|yi|,将这些水到了这些杯子里,使得价值最小,每杯水的价值为杯中水体积的平方。我们可以二分找杯中水体积的最大值,具体实现看代码。

#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int c[maxn],s[maxn];
double y[maxn],x[maxn];
const double eps=1e-6;
int main()
{
	int t,n,k,r;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&n,&k,&r);
		for(int i=1;i<=k;i++) scanf("%d",&c[i]);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=k;j++)
			{
				scanf("%d",&s[j]);
				x[j]=abs(s[j]-c[j]);
			}
			double L=0,R=1e4+100,mid;
			while(R-L>eps)
			{
				mid=(L+R)/2.0;
				double sum=0.0;
				for(int j=1;j<=k;j++)
				{
					sum+=max(0.0,x[j]-mid);
				}
				if(sum<=r) R=mid;
				else L=mid;
			}
			for(int j=1;j<=k;j++)
			{
				if(x[j]>L) x[j]=L;
				if(s[j]-c[j]>0)
				{
					if(j==k) printf("%.4lf\n",s[j]-x[j]);
					else printf("%.4lf ",s[j]-x[j]);
				}
				else
				{
					if(j==k) printf("%.4lf\n",s[j]+x[j]);
					else printf("%.4lf ",s[j]+x[j]);
				}
			}
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值