题意:
需要选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; }