uva 714 Copying Books
Thinking about it:
看完这题的时候,确实没有啥思路,看了题解才明白的。这个最小值是通过二分法先确定下来的,然后才能分组。这种思维方式超出了我的意料,我还一直朝着DP的思路走。看来我还需要多磨练。
Reference:
《算法竞赛入门经典(第2版)》
Code:
/**
* AC @ Sep 5 th 2015
* Run Time : 0.000s
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 500 + 50;
int value[MAXN];
int M, K;
LL sum, maxC;
void read() {
cin >> M >> K;
sum = maxC = 0;
for (int i = 0; i < M; ++i) {
cin >> value[i];
sum += value[i];
maxC = maxC > value[i] ? maxC : value[i];
}
}
bool is_possile(int p) {
int tmpValue = 0, group = 1;
for (int i = M-1; i >= 0; --i) {
if (tmpValue + value[i] > p || i+1 <= K - group) {
tmpValue = value[i];
group ++;
} else {
tmpValue += value[i];
}
}
return group == K;
}
void print(int pos, int group, int p) {
std::vector<int> v;
int i;
LL sum = 0;
for (i = pos; sum + value[i] <= p && i+1>K-group; --i) {
sum += value[i];
v.push_back(value[i]);
}
if (group == K) { // the head
for (int l = v.size()-1; l > 0; --l) {
cout << v[l] << " ";
}
cout << v[0];
} else {
print(i, group+1, p);
cout << " /";
for (int l = v.size()-1; l >= 0; --l) {
cout << " " << v[l];
}
}
}
void output(int p) {
print(M-1, 1, p);
cout << endl;
}
void work() {
// if left is initialized with 0, some problems will occur
LL left = maxC, right = sum, mid;
while (right > left) {
mid = (right + left) >> 1;
if (is_possile(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
output(right);
}
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T --) {
read();
work();
}
return 0;
}

浙公网安备 33010602011771号