zoukankan      html  css  js  c++  java
  • poj 2976+poj3621(01分数规划

    题目:每门课有实际成绩a和总成绩b,要求去掉k门课后能得到的平均成绩的最大值。

    思路:裸的分数规划题。一个非常经典的解决问题的思路就是把求值变为判定问题,然后进行2分,分数规划就是这类思想的一个应用。、

    具体讲解参考此文章:http://blog.csdn.net/hhaile/article/details/8883652

    /*
    * @author:  Cwind
    * http://www.cnblogs.com/Cw-trip/
    * 蒟蒻只能做几个水题。。
    */
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-3)
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define FINF (1e100)
    #define INF 1000000000
    const double pi=acos(-1.0);
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> P;
    
    const int maxn=1005;
    int n,k;
    double a[maxn],b[maxn];
    double c[maxn];
    bool check(double p){
        for(int i=0;i<n;i++){
            c[i]=a[i]-p*b[i];
        }
        sort(c,c+n,greater<double>());
        double sum=0;
        for(int i=0;i<n-k;i++){
            sum+=c[i];
        }
        if(sum<0) return 0;
        else return 1;
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        while(cin>>n>>k){
            if(n==0&&k==0) break;
            for(int i=0;i<n;i++){
                scanf("%lf",&a[i]);
                a[i]*=100;
            }
            for(int i=0;i<n;i++){
                scanf("%lf",&b[i]);
            }
            double l=0,r=100;
            while(r-l>eps){
                double mid=(r+l)/2;
                if(check(mid)){
                    l=mid;
                }else{
                    r=mid;
                }
            }
            printf("%.0f
    ",l);
        }
        return 0;
    }
    View Code

     poj3621(最优比率环

    题目:求一个环使得环上的点权之和比边权之和最大。

    思路:把点权转移到边上,01分数规划求解。

    这里用到了一个黑科技:dfs加速的spfa求找负圈,主要是先把所有dis初始化为0,然后dfs,如果遇到之前栈内的点,就是找到负圈,此算法容易实现,效率很高。

    /*
    * @author:  Cwind
    * http://www.cnblogs.com/Cw-trip/
    * 蒟蒻只能做几个水题。。
    */
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-3)
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define INF 1000000000
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> P;
    
    const int maxn=1005;
    struct EDGE{
        int to;
        double d;
        EDGE(int to,double d):to(to),d(d){}
    };
    vector<EDGE> G[maxn];
    int L,M;
    double F[maxn];
    int st;
    int vis[maxn];
    double dis[maxn];
    bool dfs(int v,double p){
        vis[v]=st;
        for(int i=0;i<G[v].size();i++){
            EDGE &e=G[v][i];
            if(dis[e.to]>dis[v]-F[v]+e.d*p){
                dis[e.to]=dis[v]-F[v]+e.d*p;
                if(vis[e.to]==st) return 1;
                else if(dfs(e.to,p)) return 1;
            }
        }
        vis[v]=0;
        return 0;
    }
    bool check(double p){
        memset(vis,0,sizeof vis);
        memset(dis,0,sizeof dis);
        for(st=1;st<=L;st++){
            if(dfs(st,p)) return 1;
        }
        return 0;
    }
    int main(){
        ///freopen("/home/files/CppFiles/in","r",stdin);
        //freopen("defense.in","r",stdin);
        //freopen("defense.out","w",stdout);
        cin>>L>>M;
        for(int i=1;i<=L;i++)
            scanf("%lf",&F[i]);
        for(int i=0;i<M;i++){
            int a,b;
            double c;
            scanf("%d%d%lf",&a,&b,&c);
            G[a].pb(EDGE(b,c));
        }
        double l=0,r=1e9;
        while(r-l>eps){
            double mid=(r+l)/2;
            if(check(mid)){
                l=mid;
            }else{
                r=mid;
            }
        }
        printf("%.2f
    ",l);
        return 0;
    }
    View Code
  • 相关阅读:
    Ubuntu的启动配置文件grub.cfg(menu.lst)设置指南zz
    Qt/E客户端服务期间通信数据串行化
    开源协议简介BSD、 Apache Licence、GPL、LGPL、MIT转载
    Qt/E服务器到客户端的消息传递
    解决 Windows 和 Ubuntu 时间不一致的问题转载
    Qt/E服务器客户端架构
    Qt/E中的键盘设备管理
    Qt/E服务器客户端的通信机制
    解决 ssh 登录慢 转载
    c# 扩展方法奇思妙用变态篇一:由 Fibonacci 数列引出 “委托扩展” 及 “递推递归委托”
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4798465.html
Copyright © 2011-2022 走看看