持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情。
题目信息描述
给定一个长度为 nn 的正整数数组 a1,a2,…,ana1,a2,…,an。
你可以任意改变其中任意元素的值。
但是,改变后的元素的值仍需是正整数。
将一个元素的值从 aa 变为 bb 所需要付出的代价为 |a−b||a−b|。
对于一个正整数 tt,如果 |ai−t|≤1|ai−t|≤1,则称第 ii 个元素能够与 tt 匹配。
现在,请你指定一个正整数 tt,并且用最小的代价修改整个数组,使得数组中所有元素都能够与 tt 匹配。
指定的 tt 不同,所需付出的最小代价也可能不同。
请你合理选择正整数 tt,目标是让所需付出的最小代价尽可能小。
输入格式
第一行包含整数 TT,表示共有 TT 组测试数据。
每组数据第一行包含整数 nn。
第二行包含 nn 个整数 a1,a2,…,ana1,a2,…,an。
输出格式
每组数据输出一行结果,首先输出你选择的正整数 tt,然后输出使得数组中所有元素都能够与 tt 匹配,所需付出的最小代价。
如果 tt 有多种合理选择,则任选其一输出即可。
数据范围
1≤T≤201≤T≤20, 1≤n≤10001≤n≤1000, 1≤ai≤1001≤ai≤100, 同一测试点内所有 nn 的和不超过 10001000。
输入样例:
2
3
10 1 4
5
1 1 2 2 3
输出样例:
3 7
2 0
思路
货仓选址货仓选址!!!经典再放送!
这题本质就是一个有三个中点选择的货仓选址问题(mid,mid-1,mid+1)。只需要枚举三个点就Over了!
暴力枚举
输入数组后先排序,从最小的到大的开始枚举,找到一其中代价最小的
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int N = 1010;
int T,n;
int a[N];
int main( ) {
scanf("%d", &T);
while( T-- ) {
scanf("%d", &n);
for ( int i = 0; i < n; i++ ) scanf("%d", &a[i]);
sort(a, a + n);
int res = N, cost = 0;
int t;
for ( int i = a[0]; i <= a[n-1]; i++ ) {
cost = 0;
for( int j = 0; j < n; j++ ) {
if( fabs( a[j] - i ) > 1 ) {
if( a[j] > i ) cost += a[j] - ( i + 1 );
else if( a[j] < i ) cost += ( i - 1 ) - a[j];
}
}
if( cost < res ) {
res = cost;
t = i;
}
}
cout << t << " " << res << endl;
}
return 0;