codevs 1183 泥泞的道路 01分数规划

题目链接

 

题目描述  Description

CS有n个小区,并且任意小区之间都有两条单向道路(a到b,b到a)相连。因为最近下了很多暴雨,很多道路都被淹了,不同的道路泥泞程度不同。小A经过对近期天气和地形的科学分析,绘出了每条道路能顺利通过的时间以及这条路的长度。

现在小A在小区1,他希望能够很顺利地到达目的地小区n,请帮助小明找出一条从小区1出发到达小区n的所有路线中(总路程/总时间)最大的路线。请你告诉他这个值。

输入描述  Input Description

第一行包含一个整数n,为小区数。

接下来n*n的矩阵P,其中第i行第j个数表示从小区i到小区j的道路长度为Pi,j。第i行第i个数的元素为0,其余保证为正整数。

接下来n*n的矩阵T,第i行第j个数表示从小区i到小区j需要的时间Ti,j。第i行第i个数的元素为0,其余保证为正整数。

输出描述  Output Description

写入一个实数S,为小区1到达n的最大答案,S精确到小数点后3位。

样例输入  Sample Input

3

0 8 7 

9 0 10 

5 7 0 

0 7 6 

6 0 6 

6 2 0

样例输出  Sample Output

2.125

 

sigma(dis)/sigma(time) = x,   dis-x*time = 0。

构造图f[i][j] = dis[i][j]-mid*time[i][j], 不断二分mid逼近答案。

01分数规划感觉我还是不太理解啊=.=

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
double dis[105], f[105][105], g[105][105], t[105][105], num[105], vis[105];
int n;
int spfa() {
    for(int i = 1; i<=n; i++)
        dis[i] = -inf;
    dis[1] = 0;
    mem(vis);
    mem(num);
    vis[1] = 1;
    queue <int> q;
    q.push(1);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        vis[u] = 0;
        num[u]++;
        if(num[u]>n)
            return 1;
        for(int i = 1; i<=n; i++) {
            if(f[u][i]!=0) {
                if(dis[i]<dis[u]+f[u][i]) {
                    dis[i] = dis[u]+f[u][i];
                    if(!vis[i]) {
                        q.push(i);
                        vis[i] = 1;
                    }
                }
            }
        }
    }
    if(dis[n]>0)
        return 1;
    return 0;
}
int check(double mid) {
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<=n; j++) {
            f[i][j] = g[i][j]-mid*t[i][j];
        }
    }
    if(spfa())
        return 1;
    return 0;
}
int main()
{
    cin>>n;
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<=n; j++) {
            scanf("%lf", &g[i][j]);
        }
    }
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<=n; j++) {
            scanf("%lf", &t[i][j]);
        }
    }
    double l = 0, r = inf;
    while(fabs(r-l)>eps) {
        double mid = (l+r)/2;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    printf("%.3f\n", l);
    return 0;
}

 

你可能感兴趣的:(codevs 1183 泥泞的道路 01分数规划)