题目链接:https://vjudge.net/problem/HihoCoder-1835
题解:首先我们应该能想到到达图形的距离最近那肯定是垂直过去,也就是坐标变为(x1 - k, x2 - k, x3 - k...),假设图形原点的坐标为(x10, x20, x30 ...),如果某个xi - k == xi0 了,那么我们就不在让他减小了,也就是说当前维已经达到了最优的情况,因此我们每次减去一个最小的xi即可,减到不能减为止,也就是该点已经到达了图形的边界,其实这样找的时候是可以O(1)找出来的,但训练的时候是二分写的,复杂度也只是加个log而已
二分:
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-8
struct node {
double x[110];
}p[55];
int n, k;
double r;
double judge(int pos, double x, double ans, double cnt) {
return ans - cnt * x ;
}
int main() {
int T;
double ll, rr, mid;
double cnt, tmp, ans;
int id;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &k);
scanf("%lf", &r);
for(int i = 0; i <= n; i++)
for(int j = 1; j <= k; j++)
scanf("%lf", &p[i].x[j]);
for(int i = 1; i <= n; i++) {
rr = -1.0;
ll = 0;
ans = 0;
cnt = 0;
for(int j = 1; j <= k; j++) {
ans += fabs(p[0].x[j] - p[i].x[j]);
if(fabs(p[0].x[j] - p[i].x[j]) > eps) {
cnt += 1;
}
if(fabs(p[0].x[j] - p[i].x[j]) > eps && (rr < 0 || rr > fabs(p[0].x[j] - p[i].x[j])))
rr = fabs(p[0].x[j] - p[i].x[j]);
}
cnt = 0;
// cout << fabs(judge(i, ll) - r) << endl;
while(fabs(judge(i, ll, ans, cnt) - r) > 0.000001) {
for(int j = 1; j <= k; j++) {
if(fabs(p[0].x[j] - p[i].x[j]) < eps) continue;
if(p[0].x[j] > p[i].x[j]) p[i].x[j] += ll;
else p[i].x[j] -= ll;
}
rr = -1.0;
ll = 0;
cnt = 0;
ans = 0;
for(int j = 1; j <= k; j++) {
if(fabs(p[0].x[j] - p[i].x[j]) > eps && (rr < 0 || rr > fabs(p[0].x[j] - p[i].x[j])))
rr = fabs(p[0].x[j] - p[i].x[j]);
ans += fabs(p[0].x[j] - p[i].x[j]);
if(fabs(p[0].x[j] - p[i].x[j]) > eps) {
cnt += 1;
}
}
while(rr - ll > eps) {
mid = (ll + rr) / 2;
if(judge(i, mid, ans, cnt) <= r) {
rr = mid;
} else {
ll = mid;
}
}
}
for(int j = 1; j <= k; j++) {
if(fabs(p[0].x[j] - p[i].x[j]) < eps) printf("%.4f", p[i].x[j]);
else if(p[0].x[j] > p[i].x[j]) printf("%.4f", p[i].x[j] + ll);
else printf("%.4f", p[i].x[j] - ll);
printf("%c", " \n"[j == k]);
}
}
}
return 0;
}
/*
1 2
1
0 0
1.1 0.4
5 1
*/
O(1)找:
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-8
struct node {
double x[110];
}p[55];
int n, k;
double r;
double judge(int pos, double x, double ans, double cnt) {
return ans - cnt * x ;
}
int main() {
int T;
double ll, rr, mid;
double cnt, tmp, ans;
int id;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &k);
scanf("%lf", &r);
for(int i = 0; i <= n; i++)
for(int j = 1; j <= k; j++)
scanf("%lf", &p[i].x[j]);
for(int i = 1; i <= n; i++) {
rr = -1.0;
ll = 0;
ans = 0;
cnt = 0;
for(int j = 1; j <= k; j++) {
ans += fabs(p[0].x[j] - p[i].x[j]);
if(fabs(p[0].x[j] - p[i].x[j]) > eps) {
cnt += 1;
}
if(fabs(p[0].x[j] - p[i].x[j]) > eps && (rr < 0 || rr > fabs(p[0].x[j] - p[i].x[j])))
rr = fabs(p[0].x[j] - p[i].x[j]);
}
cnt = 0;
while(1) {
// cout << " *\n";
for(int j = 1; j <= k; j++) {
if(fabs(p[0].x[j] - p[i].x[j]) < eps) continue;
if(p[0].x[j] > p[i].x[j]) p[i].x[j] += ll;
else p[i].x[j] -= ll;
}
rr = -1.0;
ll = 0;
for(int j = 1; j <= k; j++)
if(fabs(p[0].x[j] - p[i].x[j]) > eps && (rr < 0 || rr > fabs(p[0].x[j] - p[i].x[j])))
rr = fabs(p[0].x[j] - p[i].x[j]);
cnt = 0;
ans = 0;
for(int j = 1; j <= k; j++) {
ans += fabs(p[0].x[j] - p[i].x[j]);
if(fabs(p[0].x[j] - p[i].x[j]) > eps) {
cnt += 1;
}
}
if(ans <= eps + 1) {
ll = 0;
break;
}
if(ans - cnt * rr <= r + eps) {
ll = (ans - r) / cnt;
break;
}
ll = rr;
}
for(int j = 1; j <= k; j++) {
if(fabs(p[0].x[j] - p[i].x[j]) < eps) printf("%.4f", p[i].x[j]);
else if(p[0].x[j] > p[i].x[j]) printf("%.4f", p[i].x[j] + ll);
else printf("%.4f", p[i].x[j] - ll);
printf("%c", " \n"[j == k]);
}
}
}
return 0;
}
/*
1 2
1
0 0
1.1 0.4
5 1
*/