Communication System dp 动态规划 || 贪心

题意: 你要写一个社交系统 需要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);
	}
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值