poj 1018 dp
2016-03-18 15:09
447 查看
一、题目大意
一个系统由n个设备组成,每个设备可以由mi个厂商提供,每个设备你可以选一个厂商,在你选定的厂商的设备中,b(带宽)是所选设备中b值最小的,类似于短板效应,p是所有价格之和,要求b/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
b/p = 120 / 185
二、代码
贪心算法:#include <iostream> #include <cmath> #include <cstring> using namespace std; const int Max=101; struct node //每对厂商给出数据 { double b; double p; }; node a[Max][Max]; double b[Max*Max]; //b另外开辟的数组 int m[Max]; int bsize; int cmp(const void *a,const void *b) { return (*(double *)a)-(*(double *)b); } int main() { int t,n; cin>>t; while (t--) { memset(a,0,sizeof(a)); memset(m,0,sizeof(m)); cin>>n; int i,j,k; int bsize=0; //输入数据 for (i=0;i<n;i++) { cin>>m[i]; for (j=0;j<m[i];j++) { cin>>a[i][j].b>>a[i][j].p; b[bsize++]=a[i][j].b; } } qsort(b,bsize,sizeof(b[0]),cmp); //带宽b排序,方便枚举 double mmax=0; double mmin; double sump=0; double temp=0; for (i=0;i<=bsize-1;i++) { //从最小带宽开始枚举,用贪心法选出带宽大于等于最小带宽的最低价格 //然后再比较更新最大的(B/P)的值,直到到达最大带宽 //如果从带宽枚举上去,一定符合要求 sump=0; int changFlag = 0; //剪枝 for (j=0;j<n;j++) { mmin=32767; for (k=0;k<m[j];k++) { if (a[j][k].b>=b[i]&&a[j][k].p<mmin) { mmin=a[j][k].p; changFlag = 1; } } sump+=mmin; } if(!changFlag) break; temp=b[i]*1.0/sump; if(temp>mmax) mmax=temp; } printf("%.3lf\n",mmax); } return 0; }
DP:
我们定义状态dp[i][j] 表示取到第i个设备带宽为j的最小的价格
很容易得到转移方程 :dp[i][j]=min(dp[i][j],dp[i-1][k]+p);
注意选择 j 的时候的大小情况。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int inf = 0x3f3f3f3f; int dp[120][1200]; int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); for(int i=1; i<=n; i++) //初始化,开始费用无穷大 { for(int j=0; j<1100; j++) dp[i][j]=inf; } for(int i=1; i<=n; i++) //dp { int num; scanf("%d",&num); for(int j=1; j<=num; j++) { int p,b; scanf("%d%d",&b,&p); if(i==1) { dp[1][b]=min(dp[1][b],p); } else { for(int k=0; k<1100; k++) { if(dp[i-1][k]!=inf) { //dp[i][j] 取到第i个设备带宽为j的最小的价格 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; for(int i=0; i<1100; i++) { if(dp [i]!=inf) //此处还可以剪枝 { double k=(double)i/dp [i]; if(k>ans) ans=k; } } printf("%.3lf\n",ans); } return 0; }
相关文章推荐
- 音视频同步(播放)原理
- Android学习之RecyclerView
- iOS 从git拷贝Xcode的snippets
- 压缩感知重构算法之OMP算法python实现
- 关于dev_set_drvdata()和dev_get_drvdata()
- 如何排序 MFC的CStringArray
- SilkTest入门快打2-编写脚本测试
- linux
- Mybatis缓存
- 基于jQuery实现收缩展开功能
- PropertyChangeSupport类
- 【Uva11468】Substring【AC自动机】【概率DP】
- composer遇到Your configuration does not allow connection to http://的问题怎么解决
- 四元数与欧拉角之间的转换
- 音频 帧率 音视频同步
- (蓝桥杯)历届试题 国王的烦恼 (并查集)
- 抓鸡直播截图(南非蚂蚁巨作)
- IOS设备设计完整指南
- Server对象(是属性)
- 前端模板引擎arttemplate.js 学习之include方法