在DP专题里做的,后来看别人的解题报告,发现其实还可以用贪心做。。。(其实也就是把DP优化了结果)
题意:
有n种装备,每种装备有m种供应商,每个装备有两个性质:带宽以及价值;
现选出n种装备,那么,总装备的带宽为n种装备的最小值,价值为n个装备的价值和
怎样选,使n个装备的总带宽与总价值的比最大。
这道题的题意光是理解就理解了半天。。。纠结啊~
dp[i][j]的含义:选择到第i种装备,当带宽最小为j时,价值的最小值;
由于对于选中的装备,j 的值为带宽最小值,所以对于其他的带宽,其值都不能小于这个最小值j,如果小于的话,那么最小的带宽就要被替换。
转移方程:
d[i][j]:第i种装备的j个产品的带宽;
p[i][j]:第i种装备的j个产品的价值;
dp[i][min(j,d[i][k])]=min(dp[i][min(j,d[i][k])],dp[i-1][j]+p[i][k]);
代码:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<fstream>
using namespace std;
int dp[105][10005];
int d[105][105];
int p[105][105];
int num[105];
int main(){
// freopen("1018in.txt","r",stdin);
// freopen("1018out.txt","w",stdout);
int n;
cin>>n;
while(n--){
int m;
cin>>m;
int maxb=0;
for(int i=0;i<m;i++){
int temp;
cin>>num[i];
for(int j=0;j<num[i];j++){
cin>>d[i][j]>>p[i][j];
if(maxb<d[i][j])
maxb=d[i][j];
}
}
for(int g=0;g<=m;g++){
for(int k=0;k<=maxb;k++){
dp[g][k]=1000000000;
}
}
for(int i=0;i<num[0];i++){
dp[0][d[0][i]]=p[0][i];
}
for(int i=1;i<m;i++){
for(int j=0;j<=maxb;j++){
for(int k=0;k<num[i];k++){
dp[i][min(d[i][k],j)]=min(dp[i-1][j]+p[i][k],dp[i][min(d[i][k],j)]);
}
}
}
double res=0;
for(int k=0;k<=maxb;k++){
if(res<k*1.0/dp[m-1][k])
res=k*1.0/dp[m-1][k];
}
printf("%.3lf\n",res);
//cout<<res<<endl;
}
return 0;
}