二分问题 -挑战例题 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;
}
寻找可行解_未test

  //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;
}
未test_可能会有精度问题

 

最大化平均值

题意:

  有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;
}
最大化平均值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值