I have made a few questions about "two points + greedy" recently, and I will make a summary.
Basic Idea: reduce the scope step by second until the optimal solution
1. poj2456
/* Question: there are n bullpens, and m are selected for the ox, which is equivalent to n points on a line segment, and m points are selected to maximize the minimum distance between adjacent points: greedy + bipartite enumeration of the distance between the two adjacent cattle to determine whether the distance is equal to or greater than the distance can be put into all cattle. */# Include
# Include
# Include
Using namespace std; const int N = 1e6 + 10; int a [N], n, m; bool judge (int k) // enumeration distance k, check whether any two adjacent ox {int cnt = a [0], num = 1; // If num is 1, it indicates that the first ox has been placed in the column a [0] for (int I = 1; I <n; I ++) // enumerate the remaining columns {if (a [I]-cnt> = k) // The distance between the column a [I] and the previous column is greater than or equal to k, it means you can put it into the ox {cnt = a [I]; num ++; // and put it into another ox} if (num> = m) return true; // return false;} void solve () {int l = 1, r = a [n-1]-a [0]; // The minimum distance is 1, and the maximum distance is the while (l <r ){ Int mid = (l + r)> 1; if (judge (mid) l = mid + 1; else r = mid;} printf ("% d \ n ", r-1);} int main () {int I; while (~ Scanf ("% d", & n, & m) {for (I = 0; I <n; I ++) scanf ("% d ", & a [I]); sort (a, a + n); // sort solve ();} return 0 ;}
2. poj1064 binary pairs of Floating Point Numbers
/* Question: Give n line segments, in meters. Crop these line segments, cut out m long lines, and keep them as long as possible, the result must be accurate to the centimeter, that is, two digits after the decimal point. The value cannot be less than 1 cm. If the value is less than 1 cm, the output idea is 0.00: Binary */# include
# Include
# Include
Using namespace std; const int N = 1e6 + 10; const double eps = 1e-6; double a [N], maxx; int n, m; void solve () {double l = 0, r = maxx; double ans = 0; while (r-l> eps) {double mid = (l + r)/2.0; int sum = 0; for (int I = 0; I <n; I ++) sum + = (int) (a [I]/mid ); // calculate the number of segments that can be divided into if (sum> = m) l = mid; else r = mid;} printf ("%. 2lf \ n ", int (r * 100) * 0.01); // if r is output directly, int main () {int I; while (~ Scanf ("% d", & n, & m) {maxx = 0; for (I = 0; I <n; I ++) {scanf ("% lf", & a [I]); if (a [I]> maxx) maxx = a [I] ;} solve ();} return 0 ;}
3. nyoj914 maximize the average value
Ideas:
# Include
# Include
# Include
Using namespace std; const int N = 10010; const double eps = 1e-6; int c [N], v [N], n, m; double s [N]; bool judge (double x) {int I; for (I = 0; I <n; I ++) s [I] = v [I]-x * c [I]; sort (s, s + n); double sum = 0; for (I = 0; I <m; I ++) // select s [I] larger sum + = s [n-1-i]; return sum> = 0;} void solve () {double l = 0, r = 1000000; while (r-l> eps) {double mid = (l + r)/2; if (judge (mid )) l = mid; else r = mid;} printf ("% . 2lf \ n ", r);} int main () {while (~ Scanf ("% d", & n, & m) {for (int I = 0; I <n; I ++) scanf ("% d", & c [I], & v [I]); solve ();} return 0 ;}
4. hdu4004/nyoj619 (frog crossing the river)
/* Question: if the river is L wide, there are n stones, and frogs can jump to the other side of the river by stone. They can jump up to m times and ask the frog how far he can jump at least each time: assume that both sides of the river are stone, and a total of m jumps, if a total of m + 1 stones are used, we can convert them to pick out m + 1 stones in n stones. */# include
# Include
# Include
Using namespace std; const int N = 500010; int a [N]; int L, n, m; bool judge (int k) {int cnt = 1, pre = a [0]; // 1 indicates that the first rock has been selected for (int I = 1; I <n; I ++) {if (a [I]-pre> k) {pre = a [I-1]; cnt ++; if (a [I]-pre> k) // The distance between the two adjacent stones is greater than k return 0;} cnt ++; if (cnt> m + 1) return 0; return 1;} void solve () {int l = 0, r = L; while (l <r) {int mid = (l + r)> 1; if (judge (mid) r = mid; else l = mid + 1;} print F ("% d \ n", l);} int main () {while (~ Scanf ("% d", & L, & n, & m) {a [0] = 0; n ++; for (int I = 1; I <n; I ++) scanf ("% d", & a [I]); sort (a + 1, a + n ); a [n ++] = L; // use the opposite side of the river as the last rock solve ();} return 0 ;}
5. nyoj680)
#include
#include
#include #include
using namespace std;const int N = 1005;int a[N];int n,m,sum;bool judge(int k){ int cnt = 0, sum = 0; for(int i = 0; i < n; i ++) { if(a[i] > k) return false; sum += a[i]; if(sum > k) { sum = a[i]; cnt ++; } } cnt ++; if(cnt <= m) return true; return false;}void solve(){ int l = 0, r = sum; while(l < r) { int mid = (l+r) >> 1; if(judge(mid)) r = mid; else l = mid + 1; } printf("%d\n",l);}int main(){ while(~scanf("%d%d",&n,&m)) { sum = 0; for(int i = 0; i < n; i ++) scanf("%d",&a[i]), sum += a[i]; solve(); } return 0;}