zoukankan      html  css  js  c++  java
  • 弹珠(贪心+二分)

    https://www.luogu.org/problemnew/show/T32708

    这道题是校模拟的一道题,

    本来的朴素想法是贪心,当时得了40分,但是程序很乱

    第二次修改了数据结构,程序变得清爽许多,但是分数没有改变,后来手动加了一个特判多了二十

    第三次按照正解的思路但是仍然出了一点小bug,最后成功

    首先用贪心的时候要做一个简单的正确性证明,可以举几个特殊的例子,

    正确的做法应该是二分然后不断逼近,

    标程

    //原本是说b总和除以w总和的最大值,将其转换为b-x*w,
    //算其余下多少,不断接近
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct date{
    int wz,bz;
    float v;
    }g[1200];
    int w[6000],b[6000];//b是美丽值,w是重量
    float ps[1200];
    int n,m,k;
    int w2,b2;
    float v2;
    int ok(float x){
    for(int i=1;i<=m;i++)ps[i]=(float)(g[i].bz-x*g[i].wz);
    sort(ps+1,ps+1+m);//n,m错
    // for(int i=m;i>=1;i--)
    // cout<<ps[i]<<" ";
    float tot=0;
    for(int i=m;i>=m-k+1;i--)tot+=ps[i];//n,m错
    return tot>=0;
    }
    void solve(){
    float l=0,r=1500;
    while((r-l)>1e-3){//应用二分计算
    float mid=(l+r)/2.0;
    if(ok(mid))l=mid+1e-3;
    else r=mid-1e-3;
    }
    printf("%.2f",(l+r)/2.0);
    }
    int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    scanf("%d",&w[i]);
    int x;
    for(int i=1;i<=m;i++){
    scanf("%d",&x);
    while(x){
    g[i].wz+=w[x];
    g[i].bz+=b[x];
    scanf("%d",&x);
    }
    }
    solve();
    return 0;
    }
    /*学姐的更优雅的二分写法
    float l=0,r=1500;
    for(int time=0;time<=100;time++){
    float mid=(l+r)/2.0;
    if(ok(mid))l=mid;
    else r=mid;
    }
    printf("%.2f",(l+r)/2.0);

  • 相关阅读:
    _getch()函数的一些使用方法
    键盘敲击(keyboard hit)
    计时 GetTickCount() 函数的作用和用法
    1
    关于COLORREF的定义及用法
    C++字符串大小写转换的库函数
    数楼梯(斐波那契数列+高精度)
    回文数(内含高精度加法,字符串是否为回文的判断)
    最短路径Dijkstra算法
    经典八大排序
  • 原文地址:https://www.cnblogs.com/linzeli/p/9241193.html
Copyright © 2011-2022 走看看