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);
	}
}
时间: 2024-10-13 10:47:02

Communication System dp 动态规划 || 贪心的相关文章

POJ 1018 Communication System (动态规划)

Communication System Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22500   Accepted: 8008 Description We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices.

POJ 1018 Communication System 题解

本题一看似乎是递归回溯剪枝的方法,我一提交,结果超时. 然后又好像是使用DP,还可能我剪枝不够. 想了很久,无奈忍不住偷看了下提示,发现方法真多,有贪心,DP,有高级剪枝的,还有三分法的,八仙过海各显神通啊. 坏习惯了,没思考够深入就偷看提示了. 幸好及时回头,还不需要看别人的代码了.自己做出来之后,有空看看多种解法的代码也好. 然后我想出自己的思路了,使用贪心,剪枝,DP综合优化下,呵呵,最后程序有点复杂,优化到了16ms,运气好点,或者vector换成原始数组的话,应该可以0MS了. 总体思

zoj1409 Communication System

[题解]: [代码]: 1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #define inf 99999999 5 using namespace std; 6 int dp[105][10005];//i件设备,最小带宽(瓶颈)为j时的最小花费 7 int B[105][105]; 8 int P[105][105]; 9 int M[105],N; 10 double fmax(

poj1018 Communication System

Description We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices. For each device, we are free to choose from several manufacturers. Same devices from two manufacturers d

(转)dp动态规划分类详解

dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间效率高,代码量少,多元性强,主要考察思维能力.建模抽象能力.灵活度. ****************************************************************************************** 动态规划(英语:Dynamic programm

POJ1141 Brackets Sequence (dp动态规划,递归)

本文出自:http://blog.csdn.net/svitter 原题:http://poj.org/problem?id=1141 题意:输出添加括号最少,并且使其匹配的串. 题解: dp [ i ] [ j ] 表示添加括号的个数, pos[ i][ j ] 表示 i , j 中哪个位置分开,使得两部分分别匹配. pos [ i ][ j ] 为-1的时候,说明i, j 括号匹配. 初始值置dp [ i ] [ i ]  = 1; 如果只有一个括号,那么匹配结果必然是差1. 首先判断括号是

UVA 11651 - Krypton Number System(DP+矩阵快速幂)

UVA 11651 - Krypton Number System 题目链接 题意:给一个进制base,一个分数score求该进制下,有多少数满足一下条件: 1.没有连续数字 2.没有前导零 3.分数为score,分数的计算方式为相邻数字的平方差的和 思路:先从dp入手,dp[i][j]表示组成i,最后一个数字为j的种数,然后进行状态转移,推出前面一步能构成的状态,也就是到dp[(b - 1) * (b - 1)][x]. 然后可以发现后面的状态,都可以由前面这些状态统一转移出来,这样就可以利用

poj 1018 Communication System (枚举)

Communication System Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22380   Accepted: 7953 Description We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices.

HDU 5135 Little Zu Chongzhi&#39;s Triangles(状压dp或者贪心)

题目大意:给你n个线段让你任意组成三角形,求组出来的三角形的面积的和最大为多少. 解题思路:首先你得知道海伦公式:S = sqrt(p*(p-a)*(p-b)*(p-c)), p = (a+b+c)/2. 思路一:贪心,按照边的长度进行排序,从大到小判断如果可以构成三角形,就让他构成三角形,这样组成的三角形的面积和一定是最大的. 思路二:状压dp,先暴力求出来所有可以组成的三角形对应的状态和面积,然后dp求解,状态转移公式是:dp[i|(f[j].xnum)] = max(dp[i|(f[j].