• Binary Search


    01 分数划分

    什么 01 分数划分,叫 Binary Search 多好。

    P1642 规划

    可以二分答案 (x),考虑选择 (n-m) 个数使得答案 (ge x)

    [dfrac{sum w(i)}{sum c(i)}ge x ]

    [sum w(i)ge sum (x imes c(i)) ]

    [sum(w(i)-x imes c(i))ge 0 ]

    之后按照改变后的权值 (dp) 出答案即可。

    $ exttt{code}$
    // Author:A weak man named EricQian
    #include<bits/stdc++.h>
    using namespace std;
    #define infll 0x7f7f7f7f7f7f7f7f
    #define inf 0x3f3f3f3f
    #define Maxn 105
    typedef long long ll;
    inline int rd()
    {
    	 int x=0;
    	 char ch,t=0;
    	 while(!isdigit(ch = getchar())) t|=ch=='-';
    	 while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    	 return x=t?-x:x;
    }
    inline ll maxll(ll x,ll y){ return x>y?x:y; }
    inline ll minll(ll x,ll y){ return x<y?x:y; }
    inline ll absll(ll x){ return x>0ll?x:-x; }
    inline ll gcd(ll x,ll y){ return (y==0)?x:gcd(y,x%y); }
    int n,m,tot;
    int hea[Maxn],nex[Maxn<<1],ver[Maxn<<1];
    int w[Maxn],c[Maxn],siz[Maxn];
    double ans,d[Maxn],dp[Maxn][Maxn],tmp[Maxn];
    inline void add(int x,int y){ ver[++tot]=y,nex[tot]=hea[x],hea[x]=tot; }
    void dfs(int x,int fa)
    {
    	 dp[x][1]=d[x],siz[x]=1;
    	 for(int i=hea[x];i;i=nex[i])
    	 {
    	 	 if(ver[i]==fa) continue;
    	 	 dfs(ver[i],x);
    	 	 for(int j=1;j<=m;j++) tmp[j]=dp[x][j];
    	 	 for(int j=1;j<=min(siz[x],m);j++)
    	 	 	 for(int k=0;k<=m-j;k++)
    	 	 	 	 dp[x][j+k]=fmax(dp[x][j+k],tmp[j]+dp[ver[i]][k]);
    		 siz[x]+=siz[ver[i]];
    	 }
    }
    inline bool check(double x)
    {
    	 for(int i=1;i<=n;i++) d[i]=1.0*w[i]-1.0*x*c[i];
    	 for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j]=-2000000000.0;
    	 dfs(1,0);
    	 for(int i=1;i<=n;i++) if(dp[i][m]>=0) return true;
    	 return false;
    }
    int main()
    {
    	 //ios::sync_with_stdio(false); cin.tie(0);
    	 //freopen(".in","r",stdin);
    	 //freopen(".out","w",stdout);
    	 n=rd(),m=n-rd();
    	 for(int i=1;i<=n;i++) w[i]=rd();
    	 for(int i=1;i<=n;i++) c[i]=rd();
    	 for(int i=1,x,y;i<n;i++) x=rd(),y=rd(),add(x,y),add(y,x);
    	 double nl=0.0,nr=2000000000.0;
    	 while(nl+0.001<=nr)
    	 {
    	 	 double mid=(nl+nr)/2.0;
    	 	 if(check(mid)) ans=mid,nl=mid+0.001;
    	 	 else nr=mid-0.001;
    	 }
    	 printf("%.1lf
    ",ans);
    	 //fclose(stdin);
    	 //fclose(stdout);
    	 return 0;
    }
    
  • 相关阅读:
    vc文件读写,用fstream和CStdioFile
    使用批处理启用或禁用端口
    什么是qt,QT Creator, QT SDK, QT Designer
    C#结构体特性
    VC++对话框中添加状态栏的方法
    [转]字符编码,ansi, unicode,utf8, utf16
    TRANSACTIONAL TEXT INDEX全文索引可能消耗大量PGA内存
    解决Oracle中Split Partition缓慢的问题
    ORA00600
    计算Oracle数据库软件许可证License的使用量
  • 原文地址:https://www.cnblogs.com/EricQian/p/15495458.html
Copyright © 2020-2023  润新知