二分问题 -挑战例题 2017-7-28
poj 1064 Cable master(寻找可行解)
题意:
给出n条线段,以米的单位给出,小数点后两位(精确到厘米),要你对这些线段裁剪,裁剪出m条等长的线段,并且让这些线段尽可能长另外线段的长度不能小于1厘米,如果筹不够m条,输出0.00
思路:
1.转换成整数 接着套模板就可以了
2.check函数 里如果sum >= k说明此时可以拆分成k个 然后把区间右移 找更大的
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int mod = 1e9 + 7; const int maxn = 10000 + 5; const int INF = 0x3f3f3f3f; const double eps = 1e-7; typedef long long LL; int a[maxn]; int n,k; double len; bool check(int d) { int sum = 0; for(int i=0; i<n; i++){ sum += a[i]/d; } return sum >= k; } int main () { std::ios::sync_with_stdio(false);//关闭同步输入 while (cin >> n >> k) { int Max = 0; for(int i=0; i<n; i++) { cin >> len; a[i] = len*100; Max = max(a[i] , Max); } int ans = 0; int le = 1,ri = Max; //因为已经规划成整数问题了 所以开始就是1如果是0 会崩溃 while (le <= ri) { int mid = (le + ri)/2; if( check(mid) ) ans = mid, le = mid+1; else ri = mid -1; cout<<mid<<endl; } printf("%.2f\n",(double) ans/100.0); } return 0; }
//double类型还不熟练
#include <iostream> #include <cstdio> #include <cmath> using namespace std; const int mod = 1e9 + 7; const int maxn = 10000 + 5; const int INF = 0x3f3f3f3f; const double eps = 1e-3; typedef long long LL; double a[maxn]; int n,k; bool check(double d) { int sum = 0; for(int i=0; i<n; i++){ sum += (int) (a[i]/d); } return sum >= k; } int main() { std::ios::sync_with_stdio(false); double Max; while (cin >> n >> k) { Max = 0.0; for(int i=0; i<n; i++) cin >> a[i],Max = max (Max , a[i]); double le = 0,ri = Max, ans = 0; for(int i=0; i<100; i++) { double mid = (le+ri) /2.0; if(check (mid)) ans = mid, le = mid; else ri = mid; } printf("%.2f\n",floor (ans*100)/100); } return 0; }
最大化平均值
题意:
有n个物品的重量和价值分别是wi 和 vi。从中选出K个物品使得单位重量的价值最大
思路:
书上有思路 //利用单位价值贪心 不对的
#include <iostream>//最大化平均值 #include <cstdio> #include <algorithm> using namespace std; const int mod = 1e9 + 7; const int maxn = 10000 + 5; const int INF = 0x3f3f3f3f; typedef long long LL; int n,k; int w[maxn],v[maxn]; double s[maxn]; bool check (double d) { for(int i=0; i<n; i++){ s[i] = v[i] - d*w[i]; } sort(s,s+n); double sum = 0 ; for(int i=0; i<k; i++){ sum += s[ n-i-1 ]; } return sum >= 0; } int main() { std::ios::sync_with_stdio(false); while (cin >> n>> k) { for(int i=0; i<n; i++) cin>>w[i] >>v[i]; double le = 0, ri = INF,ans = 0; for(int i=0; i<100; i++) { double mid = (le+ri)/2.0; if( check(mid) ) ans = mid,le =mid; else ri = mid; } printf("%.2f\n",ans); } return 0; }