题意:
需要选n种设备,每种设备有k个不一样的个体,属性分别是带宽B,价格P
要求选出n种设备,使得总带宽B/总价格P 最大
其中总价格是n个价格之和,总带宽是n个设备的带宽中的最小带宽
可以用dp求解,复杂度是 o(n*m*max_b) m是每种设备的个数,max_b是最大宽带值
这里好像数据最大不超过1000,,,所以直接用1000了,正常情况下应该离散化一下。。。
最后面是离散化过的代码
没离散化:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
struct node
{
int bb,pp;
node(){}
node(int a,int b ){bb=a;pp=b;}
};
vector<node> tm[105];
int min(int a,int b) {return a<b?a:b;}
int n,m;
int dp[105][1005];
const int inf =0x7f7f7f7f;
int main()
{
int t;
cin>>t;
int x,y;
while(t--)
{
cin>>n;
int i,j,k;
for (i=1;i<=n;i++)
{
tm[i].clear();
scanf("%d",&m);
for (j=1;j<=m;j++)
{
scanf("%d%d",&x,&y);
tm[i].push_back(node(x,y));
}
}
memset(dp,inf,sizeof(dp)); //初始化为inf
for (i=0;i<tm[1].size();i++)
dp[1][tm[1][i].bb]=tm[1][i].pp; //
for (i=1;i<=n;i++)
{
for (j=0;j<=1000;j++)
{
if (dp[i-1][j]==inf) continue; //前i-1种能得到j这个带宽的情况下
for (k=0;k<tm[i].size();k++) //遍历所有第i种设备
{
if (tm[i][k].bb>=j) //此情况下,总带宽仍为j
dp[i][j]=min(dp[i][j],dp[i-1][j]+tm[i][k].pp);
else //此情况下,总带宽为b
dp[i][tm[i][k].bb]=min( dp[i][tm[i][k].bb],dp[i-1][j]+tm[i][k].pp);
}
}
}
double ans=0;
for( i=0; i<1000; i++) //求最大带宽/价格比
{
if(dp[n][i]!=inf)
{
double k=(double)i/dp[n][i];
if(k>ans)
ans=k;
}
}
printf("%.3lf\n",ans);
}
return 0;
}
离散化:(每次要查找,所以耗时500ms)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <vector>
using namespace std;
struct node
{
int bb,pp;
node(){}
node(int a,int b ){bb=a;pp=b;}
};
vector<node> tm[105];
int min(int a,int b) {return a<b?a:b;}
int n,m;
int dp[105][10005];
const int inf =0x7f7f7f7f;
int hash_b[10005];
int ok=0;
int hash_find(int x)
{
return lower_bound(hash_b+1,hash_b+1+ok,x)-hash_b;
}
int main()
{
int t;
cin>>t;
int x,y;
while(t--)
{
ok=0;
cin>>n;
int i,j,k;
for (i=1;i<=n;i++)
{
tm[i].clear();
scanf("%d",&m);
for (j=1;j<=m;j++)
{
scanf("%d%d",&x,&y);
tm[i].push_back(node(x,y));
hash_b[++ok]=x;
}
}
memset(dp,inf,sizeof(dp)); //初始化为inf
sort(hash_b+1,hash_b+1+ok);
ok=unique(hash_b+1,hash_b+1+ok)-hash_b;
for (i=0;i<tm[1].size();i++)
dp[1][hash_find(tm[1][i].bb)]=tm[1][i].pp;
for (i=1;i<=n;i++)
{
for (j=0;j<=ok;j++)
{
if (dp[i-1][j]==inf) continue; //前i-1种能得到j这个带宽的情况下
for (k=0;k<tm[i].size();k++) //遍历所有第i种设备
{
int tmp_b=hash_find(tm[i][k].bb);
if (tmp_b>=j) //此情况下,总带宽仍为j
dp[i][j]=min(dp[i][j],dp[i-1][j]+tm[i][k].pp);
else //此情况下,总带宽为b
dp[i][tmp_b]=min( dp[i][tmp_b],dp[i-1][j]+tm[i][k].pp);
}
}
}
double ans=0;
for( i=0; i<=ok; i++) //求最大带宽/价格比
{
if(dp[n][i]!=inf)
{
double bb= hash_b[i];
double k=bb/dp[n][i];
if(k>ans)
ans=k;
}
}
printf("%.3lf\n",ans);
}
return 0;
}