[HDOJ5933]ArcSoft's Office Rearrangement(贪心)

时间:2023-03-09 22:48:05
[HDOJ5933]ArcSoft's Office Rearrangement(贪心)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5933

题意:长度为nn的数组: a_1, a_2, \cdotsa​1​​,a​2​​,⋯, 每次操作要么可以merge两个相邻的数为一个, 值为两个数的和; 要么可以把一个数分裂成两个, 两个数的和为原数. 用最少的操作把数组变换成长度为KK且所有数值相等的数组, 无解输出-1−1

读错题了啊…以为是任意merge,题意是相邻的merge。

分情况讨论,每次判断当前点是比avg大还是小,如果大的话就把多余的部分放到下一个点上,拆操作是商-1次。余数merge到下一个的操作是2次(一次拆,一次merge),如果小于平均的话就全merge到上一个去。 当然考虑当前和下一个的和能不能作为一次。

 #include <bits/stdc++.h>
using namespace std; typedef long long LL;
const int maxn = ;
int n, k;
LL a[maxn];
LL avg; int main() {
// freopen("in", "r", stdin);
int T, _ = ;
scanf("%d", &T);
while(T--) {
scanf("%d%d",&n,&k);
printf("Case #%d: ", _++);
avg = ;
LL s = ;
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
s += a[i];
}
if(s % k != ) {
puts("-1");
continue;
}
avg = s / k;
LL ret = ;
for(int i = ; i <= n; i++) {
if(a[i] < avg) {
if(a[i] + a[i+] <= avg) {
ret++;
a[i+] = a[i] + a[i+];
}
else {
a[i+] = a[i+] - avg + a[i];
ret += ;
}
}
else if(a[i] > avg) {
LL p = a[i] / avg;
LL q = a[i] % avg;
if(q != ) {
a[i+] += q;
ret += ;
}
ret += p - ;
}
}
printf("%I64d\n", ret);
}
return ;
}