POJ - 1018 Communication System

题目大意:某公司要建立一套通信系统,该通信系统需要n种设备,而每种设备分别可以有m1、m2、m3、…、mn个厂家提供生产,而每个厂家生产的同种设备都会存在两个方面的差别:带宽bandwidths 和 价格prices。

现在每种设备都各需要1个,考虑到性价比问题,要求所挑选出来的n件设备,要使得B/P最大。

其中B为这n件设备的带宽的最小值,P为这n件设备的总价。

解题思路: 我们定义状态dp 【i】【j】 表示选择了前 i 个宽带其容量为 j 的最小费用。

很容易得到转移方程 :dp【i】【j】=min(dp【i】【j】,dp【i-1】【k】+p);

注意选择 j 的时候的大小情况。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int DP[2][1200], B[110][110], P[110][110], m[110];

int main() {
    int T, n;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        int MAX = 0, MIN = 0x3f3f3f3f;
        for (int i = 0; i < n; i++) {
            scanf("%d", &m[i]);
            for (int j = 0; j < m[i]; j++) {
                scanf("%d%d", &B[i][j], &P[i][j]);
                MAX = max(MAX, B[i][j]);
                MIN = min(MIN, B[i][j]);
            }
        }

        int cur = 1, pre = 0;
        memset(DP[pre], 0x3f3f3f3f, sizeof(int) * (MAX + 1));
        for (int j = 0; j < m[0]; j++)
            DP[pre][B[0][j]] = P[0][j];

        for (int i = 1; i < n; i++) {
            memset(DP[cur], 0x3f3f3f3f, sizeof(int) * (MAX + 1));
            for (int j = 0; j < m[i]; j++)  {
                for (int k = MIN; k <= MAX; k++)
                    if (k <= B[i][j]) 
                        DP[cur][k] = min(DP[cur][k], DP[pre][k] + P[i][j]);
                    else 
                        DP[cur][B[i][j]] = min(DP[cur][B[i][j]], DP[pre][k] + P[i][j]);
            }
            swap(cur, pre);
        }

        double ans = 0;
        for (int k = MIN; k <= MAX; k++)
            if (DP[pre][k] != 0x3f3f3f3f)
                ans = max(ans, 1.0 * k / DP[pre][k]);

        printf("%.3f\n", ans);
    }
    return 0;
}

你可能感兴趣的:(POJ - 1018 Communication System)