POJ 1505:二分枚举+贪心
二分枚举解空间+贪心判断解可行性的方法,适合很多形如求解Min{Max{…}}、Max{Min{…}}且具有单调性的问题。像:
POJ 1505 Copying Books 求:分配方案,使最后完成的时间最短。
POJ 1771 Elevator Stopping Plan 求:电梯停靠策略,使最后一个到达办公室的时间最短。
…
还有今年ICPC world final的Problem A (A Careful Approach) 求:飞机停靠方案,使得最短停靠时间间隔最大。
/** * POJ 1505 Copying Books * 算法:二分 + 贪心 */ #include <cstdio> #define N 501 typedef long long INT64; int p[N]; int T,m,k; INT64 min, max, mid; bool isAssignOK() { int i, t = 1, sum = 0; for(i = m - 1; i >= 0; --i) { if(sum + p[i] > mid) { t++; if(t > k) return false; sum = p[i]; } else sum += p[i]; } return true; } void print() { int i, j, t = 1, sum = 0; bool e[N] = {false}; for(i = m - 1; i >= 0; --i) { if(sum + p[i] > max) { t++; sum = p[i]; e[i] = true; } else sum += p[i]; if(k - t == i + 1) { for(j = 0; j <= i; ++j) e[j] = true; break; } } for(i = 0; i < m - 1; ++i) { printf("%d ", p[i]); if(e[i]) printf("/ "); } printf("%d/n", p[m-1]); } int main() { int i; scanf("%d", &T); while(T--) { scanf("%d%d", &m, &k); min = 0; max = 0; for(i = 0; i < m; ++i) { scanf("%d", p+i); max += p[i]; min = (p[i] > min) ? p[i] : min; } while(min < max) { mid = (min + max) / 2; if(isAssignOK()) max = mid; else min = mid + 1; } print(); } return 0; }