题解

1 条题解

  • 1
    @ 2017-10-23 16:56:56

    0/1分数规划
    二分答案 + 费用流

    
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    #define INF 1e9 + 7
    #define eps 1e-7
    
    using namespace std;
    
    const int Maxn = 205;
    const int N = 20100;
    
    struct node {
        double val; short cap, to, next;    
    } e[N];
    
    short n, a[Maxn][Maxn], b[Maxn][Maxn], tot = 1, h[Maxn], S, T, s, pre[Maxn], cur[Maxn];
    double dis[Maxn];
    bool vis[Maxn];
    
    inline char NC(void)
    {
      static char buf[100000], *p1 = buf, *p2 = buf;
      if (p1 == p2) {
        p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);
        if (p1 == p2) return EOF;
      }
      return *p1++;
    }
    
    inline int read() {
        static char c; c = NC();  int x;
        static int minus; minus = 1;
        for (x = 0; !(c >= '0' && c <= '9'); c = NC()) if(c == '-') minus = -1;
        for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = NC()); x *= minus;
        return x;
    }
    
    inline void Link(int u, int v, int c, double w) {
        e[++tot].to = v; e[tot].next = h[u];
        e[tot].cap = c; e[tot].val = w; h[u] = tot;    
    }
    
    inline void Add(int u, int v, int c, double w) {
        Link(u, v, c, w); Link(v, u, 0, -w);
    }
    
    short Dfs(short u, short Min) {
        if(u == T) return Min;
        int w, used = 0; vis[u] = 1;
        for(short i = h[u]; i; i = e[i].next){
            if(!vis[e[i].to] && e[i].cap && dis[e[i].to] + e[i].val == dis[u]){
                w = Dfs(e[i].to, min(e[i].cap, Min));
                e[i].cap -= w; e[i ^ 1].cap += w;
                used += w; if(used == Min)return Min;
            }
        }
        if(used == 0) vis[u] = 1;
        return used;
    }
    
    inline bool Bfs() {
        double Min = 1e100;
        for(short i = S; i <= T; ++i)
            if(vis[i])
                for(short j = h[i]; j; j = e[j].next)
                    if(!vis[e[j].to] && e[j].cap){
                        Min = min(Min, dis[e[j].to] + e[j].val - dis[i]);
                    }
        if(Min == 1e100) return 0;
        for(short i = S; i <= T; ++i) if(vis[i]) {dis[i] += Min; vis[i] = 0;}
        return 1;
    }
    
    double Check1(float c) {
        memset(dis, 0 ,sizeof(dis));
        for(register short i = 2; i <= tot; ++i) {
            if(e[i].to >= n + 1 && e[i].to <= n + n && e[i ^ 1].to >= 1 && e[i ^ 1].to <= n) {
                int u = e[i ^ 1].to, v = e[i].to - n;
                e[i].cap = 1; e[i].val = c * (double)b[u][v] - (double)a[u][v];
                e[i ^ 1].cap = 0; e[i ^ 1].val = -e[i].val;
            }
            if(e[i ^ 1].to == S) e[i].cap = 1, e[i ^ 1].cap = 0;
            if(e[i].to == T) e[i].cap = 1, e[i ^ 1].cap = 0;
        }
        double res = 0; int s = 0;
        do{
            double temp = 0;
            while(temp = Dfs(S, 32000)){
                memset(vis, 0, sizeof(vis));
                res += temp * dis[S];
            }
        } while(Bfs());    
        
        double A = 0, B = 0;
        for(int i = 2; i <= tot; ++i) {
            int u = e[i ^ 1].to, v = e[i].to;
            if(u >= 1 && u <= n && v >= n + 1 && v <= n + n && e[i].cap == 0) {
                A += a[u][v - n]; B += b[u][v - n];
            }
        }
        return A / B;
    }
    
    int main() {
    //    freopen("ball.in", "r", stdin);
    //    freopen("ball.out", "w", stdout);
        n = read(); T = n + n + 1;
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) a[i][j] = read();
        }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) b[i][j] = read();
        }
        for(int i = 1; i <= n; ++i) {
            Add(S, i, 1, 0); Add(i + n, T, 1, 0);
            for(int j = 1; j <= n; ++j) Add(i, j + n, 1, 0);
        }
        double l = 0, r;
        while(true) {
            r = Check1(l);
            if(r - l < eps) break;
            l = r;
        }
        printf("%.6lf\n", r);
        return 0;
    }
    
    
    
  • 1

信息

ID
2016
难度
5
分类
(无)
标签
递交数
76
已通过
27
通过率
36%
被复制
2
上传者