题意: 你要写一个社交系统 需要n个零件 你由n个开发商 每个开发商提供 w个零件给你 你可以从每个开发商那拿一个零件 有一个宽带值 和 价格
使得最后的性价比(B/P) 最高
B 为你选择的n个零件中的min P 为你选择n个零件的总和
思路: 当 b 值 一定的情况使得性价比最高 我们只需要求得 选择n个零件的最小值 dp【i】 = min dp【i-1】+p,dp【i】
当b不定的时候
当b不定的时候 我们设 dp【i】【j】 为选i个零件到达 j宽带的最大值
k 为 其他宽带的值
dp【i】【j】 = min(dp【i-1】【j】,dp【i-1】【k】 +p);
样例:
1 3 3 100 25 150 35 80 25 2 120 80 155 40 2 100 100 120 110
150 35
155 40
120 110
120/185=0.649
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<stdlib.h> using namespace std; const int inf = 0xffffff; int t; int dp[105][1005]; int a[105]; int main() { scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i = 0 ; i <= n; i++) for(int j = 0 ; j <= 1005; j++)//初始化 动态ps:初始化的细节问题 一种问法是恰好装好背包 f【0】]=0 f【1~n】设置为-~(无穷) 这样可以保证最终的到de f【n】为一种 dp[i][j] = inf;<pre name="code" class="cpp">/*恰好装满背包的最优解 反之依然 背包九讲*/ int b,p; //宽带 和 价格 for(int i=1; i<=n; i++) { scanf("%d",&a[i]); for(int j = 1; j <= a[i]; j++) { scanf("%d%d",&b,&p); if(i==1) dp[1][b] = min(dp[1][b],p); else { for(int k = 0; k < 1005; k++) { if(dp[i-1][k] != inf) { if(k<=b) { dp[i][k] = min(dp[i][k],dp[i-1][k] + p); } else { dp[i][b] = min(dp[i][b],dp[i-1][k] + p); } } } } } } double ans = 0.0; for(int i = 0; i < 1005; i++) { if(dp[n][i] != inf) { double ret = i*1.0 / dp[n][i];//注意1.0 double 细节 if(ret > ans) ans = ret; } } printf("%.3lf\n",ans); } }
int b,p;//宽带 和 价格 for(int i=1; i<=n; i++) { scanf("%d",&a[i]); for(int j = 1; j <= a[i]; j++) { scanf("%d%d",&b,&p); if(i==1) dp[1][b] = min(dp[1][b],p); else { for(int k = 0; k < 1005; k++) { if(dp[i-1][k] != inf) { if(k<=b) { dp[i][k] = min(dp[i][k],dp[i-1][k]
+ p); } else { dp[i][b] = min(dp[i][b],dp[i-1][k] + p); } } } } } } double ans = 0.0; for(int i = 0; i < 1005; i++) { if(dp[n][i] != inf) { double ret = i*1.0 / dp[n][i];//注意1.0 double 细节
if(ret > ans) ans = ret; } } printf("%.3lf\n",ans); }}
贪心解法 :
思路就简单多了 每次选性价比最高的那个
poj 友情提供
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; struct node { int bandwidth, price, kind; }; node divice[10001]; int num[101]; bool cmp( node a, node b ) { if ( a.bandwidth < b.bandwidth ) return true; else if ( a.bandwidth == b.bandwidth ) { if ( a.price < b.price ) return true; else if ( a.price == b.price ) { if ( a.kind < b.kind ) return true; else return false; } else return false; } else return false; } int main() { int testNumber; scanf("%d", &testNumber); for ( int testCount = 1 ; testCount<= testNumber ; testCount ++ ) { int number; scanf("%d", &number); int count = 0; int maxWidth[101]; for ( int i = 0 ; i < number ; i ++ ) maxWidth[i] = 0; for ( int i = 0 ; i < number ; i ++ ) { scanf("%d", &num[i]); for ( int j = 0 ; j < num[i] ; j ++ ) { scanf("%d%d", &(divice[count].bandwidth), &(divice[count].price)); divice[count].kind = i; if ( divice[count].bandwidth > maxWidth[i] ) maxWidth[i] = divice[count].bandwidth; count ++; } } sort( divice, divice+count, cmp ); int minMaxWidth = 9999999; for ( int i = 0 ; i < number ; i ++ ) { if ( maxWidth[i] < minMaxWidth ) minMaxWidth = maxWidth[i]; } double maxResult = 0; for ( int i = 0 ; i < count - number + 1 ; i ++ ) { int minPrice[101]; for ( int j = 0 ; j < number ; j ++ ) { minPrice[j] = 9999999; } int tempBandwidth = divice[i].bandwidth, tempPrice = divice[i].price, tempKind = divice[i].kind; for ( int j = i + 1 ; j < count ; j ++ ) { if ( divice[j].kind != tempKind && divice[j].price < minPrice[divice[j].kind] ) minPrice[divice[j].kind] = divice[j].price; } for ( int j = 0 ; j < number ; j ++ ) { if ( j != tempKind ) tempPrice += minPrice[j]; } if ( maxResult < (double)tempBandwidth/tempPrice ) maxResult = (double)tempBandwidth/tempPrice; } printf("%.3f\n", maxResult); } }