• 小咪买东西(二分+01分数规划)


    小咪买东西

    小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(n个)手办,但他是一个很怪的人,每次只想买k个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费=max。请你来看看,他会买哪些东西吧。

    输入描述:

    多组数据。
    第一行一个整数T,为数据组数。
    接下来有T组数据。
    对于每组数据,第一行两个正整数n,k,如题。
    接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。

    输出描述:

    对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。
    示例1

    输入

    1
    5 1
    1 2
    2 3
    3 4
    4 5
    5 6

    输出

    2

    分析:这道题要求单位价值(题目中的总价值/总花费)最大,假设单位价值为x,那么可以知道,x = Σv / Σc。
    将公式变形得到 Σv - Σc * x = 0 我们要求的是x的最大值,只要我们保证在式子Σv - Σc * x > 0的前提下,使x尽量大就可以。
    x可以枚举,但是限于题目数据,需要使用二分进行查找枚举。x的初始范围只需要设定在题目所给范围内(1~1e4)即可。
    可以用数组w来存储每个v和c通过公式v-c*x得到的值,然后对w[]再进行从大到小的排序,前k个就是所需要的。
    前k个的和sum如果大于等于0,说明x还可以再大,如果小于零,需要让变小些。这就是二分的选择条件。

    代码如下:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1e4+10;
    const int inf=0x3f3f3f3f;
    int n,k;
    int c[maxn],v[maxn];
    double w[maxn];
    bool judge(double x)
    {
        for(int i=1;i<=n;i++)
        {
            w[i]=v[i]-x*c[i];
        }
        sort(w+1,w+1+n,greater<double>());
        double sum=0;
        for(int i=1;i<=k;i++)
        {
            sum+=w[i];
        }
        return sum>=0;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&c[i],&v[i]);
            }
            int l=1,r=maxn;
            while(l<=r)
            {
                double mid=(l+r)/2;
                if(judge(mid))
                l=mid+1;
                else
                r=mid-1;
            }
            printf("%d
    ",(int)r);
        }
        return 0;
    }
    公式的变形并对其进行分析是二分中一个重要的点,找到关键未知数,进行二分查找,判断是否符合条件。
    题目 解方程 也是通过对公式的观察分析得出
    可以仅通过枚举a,b的值,用公式ax2+bx+c=0变形-c=a*x*x+b*x 来二分查找-c是否在所给数中判断是否符合题意。
    代码如下:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1010;
    int a[maxn];
    int n,x;
    bool findc(int num)
    {
        int l=1,r=n;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(a[mid]<num)
            l=mid+1;
            else if(a[mid]>num)
            r=mid-1;
            else
            return true;
        }
        return false;
    }
    int main()
    {
        cin>>n>>x;
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        bool flag=false;
        for(int i=1;i<=n;i++)
        {
        for(int j=1;j<=n;j++)
            {
                int c=a[i]*x*x+a[i]*x;
                if(findc(-c))
                {
                    flag=true;
                    break;
                }
            }
        }
        if(flag)
        printf("YES");
        else
        printf("NO");
        return 0;
    }
    
    
    
     


  • 相关阅读:
    Displaying Tabbed and Stacked Canvas Using Show_View In Oracle Forms
    Sort Detail Data Block Example
    Oracle Forms Execute_Query Example To Fetch The Records From Database
    web交互方式
    Ajax、Comet与Websocket
    Websocket和PHP Socket编程
    websocket webworker
    Android消息推送
    游戏服务器
    Comet:基于 HTTP 长连接的“服务器推”技术
  • 原文地址:https://www.cnblogs.com/theshorekind/p/14406323.html
Copyright © 2020-2023  润新知