POJ1018(DP)

来源:互联网 发布:车辆轨迹 大数据分析 编辑:程序博客网 时间:2024/06/11 00:19

题目链接:http://poj.org/problem?id=1018

用数组a[i][j][0]表示第 i 个设备第 j 个公司提供的带宽,a[i][j][1]表示费用。

一开始用分组背包,f[i][j]表示前 i 个设备花费 j 费用所能得到的最大带宽,那么 f[i][j] = max{f[i-1][j-a[i][j][1]] + a[i][j][0]},但是超时,因为费用是累加的,这样费用的循环上界就是每台设备对应的最大费用的总和,就是这样会超时的。

后来把 f[i][j] 的意义改为前 i 台设备获得的最大的带宽为 j 时最小费用,这样带宽的循环上界就是所有的带宽最大的哪一个,这样上界就能减小好多(让人生气的是,竟然没有给出数据范围,气死我了)。

#include<cstdio>#include<iostream>#include<fstream>#include<cstring>#include<vector>#include<utility>#define MAX(a,b) (a) > (b) ? (a) : (b)#define MIN(a,b) (a) < (b) ? (a) : (b)using namespace std;int main(){    int t;    int n;    scanf("%d",&t);    while (t > 0)    {        t--;        long long f[110][1010] = {0};        int a[110][110][2] = {0};        int m[110] = {0};        scanf("%d",&n);        int Max = 0;        for (int i=1; i<=n; i++)        {            scanf("%d",&m[i]);            for (int j=1; j<=m[i]; j++)            {                scanf("%d%d",&a[i][j][0],&a[i][j][1]);                Max = MAX(Max, a[i][j][0]);            }        }        memset(f,127,sizeof(f));        f[0][0] = 0;        for (int j=0; j<=m[1]; j++)            f[1][a[1][j][0]] = a[1][j][1];        for (int i=2; i<=n; i++)        {            for (int k=1; k<=m[i]; k++)            {                for (int j=0; j<=a[i][k][0]; j++)  //对于不超过该公司提供的带宽的情况,所得到的带宽就是j                    f[i][j] = MIN(f[i][j], f[i-1][j] +a[i][k][1]);                for (int j=a[i][k][0]+1; j<=Max; j++)   //对于超过带宽的情况,得到的带宽就是a[i][j][0]                    f[i][a[i][k][0]] = MIN(f[i][a[i][k][0]],f[i-1][j]+a[i][k][1]);            }        }        double ans = 0;        for (int j=1; j<=Max; j++)            ans = max(ans,j*1.0/f[n][j]*1.0);        printf("%.3f\n",ans);    }    return 0;}


0 0
原创粉丝点击