[2016-3-28 Test]
2016-03-28 16:29
399 查看
/* 小Z 的袜子 Description ZYB 很喜欢袜子,他决定送一些袜子给机房里的人。机房里有n 个人,但是他们脚的尺码可能不一样, 一共有m 种尺码,第i 个人的尺码为j 的概率为aij(ai1+...+aim=1)。 ZYB会带来n双袜子,并逐个询问机房里的人,如果他的尺码的袜子还有,ZYB就会送给他一双,否则将他跳过。 ZYB想知道他带n 双袜子来最多期望送出几双。 读入格式 第一行读入两个数n和m,接下来n行每行读入m 个整数表示aij*1000。 输出格式 输出一个数表示答案。 Sol: 先不考虑一个人要带多少种什么样的袜子 考虑不同种的袜子。 如果给定n个人,带某种袜子,他期望送出的袜子是和别的种类的袜子无关 而又由于期望的线性性质,E(X) = p1*E(x1)+p2*E(x2)+....+pn*E(xn) 我们只要dp出n个人,第k种袜子,带j双期望能送出多少双。 dp[i][j][k]表示前i个人,带j双尺码为k的袜子,期望能送出多少双 g[i][j], n个人,带i双尺码为j的袜子,期望能送出多少双 那么g[i][j]=dp[n][i][j] 现在考虑不同种的袜子装包 f[i][j], 前i种袜子,共带j双袜子,期望能送出多少双 f[i][j] = max(f[i-1][k]+g[j-k][i]) 就可以O(n^3)解决了 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 3010 using namespace std; int n, m; double p[maxn][maxn/10]; double dp[110][110][110], g[110][110], f[110][110]; int main(){ //freopen("gift.in", "r", stdin);freopen("gift.out", "w", stdout); scanf("%d%d", &n, &m); int x; for(int i = 1; i <= n; i ++){ for(int j = 1; j <= m; j ++){ scanf("%d", &x); p[i][j] = x / 1000.0; } } //前i个人,带j双尺码为k的袜子,期望能送出多少双 for(int k = 1; k <= m; k ++) for(int i = 1; i <= n; i ++) for(int j = 1; j <= i; j ++) dp[i][j][k] = (dp[i-1][j-1][k] + 1) * p[i][k] + dp[i-1][j][k] * (1 - p[i][k]); //g[i][j], n个人,带i双尺码为j的袜子,期望能送出多少双 for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) g[i][j] = dp [i][j]; //f[i][j],前i种袜子,共带j双袜子,期望能送出多少双 //f[i][j] = max(f[i-1][k]+g[j-k][i]) for(int i = 1; i <= m; i ++) for(int j = 0; j <= n; j ++) for(int k = 0; k <= j; k ++) f[i][j] = max(f[i][j], f[i-1][k] + g[j-k][i]); printf("%.12f\n", f[m] ); return 0; }
/* 对选择的每一双袜子统计贡献。显然选择同一种袜子多次,贡献会越来越小。 于是先通过计算g [1][i]来计算每种袜子选第一双的贡献。 然后每次选择贡献最大的进行更新。 更新时通过计算g [now+1][i]得出再选一双这种袜子的贡献, 然后加入堆中。总共只会计算n+m次贡献。 效率:n(n+m)logm 期望得分100 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define maxn 3010 using namespace std; int n, m; struct Pair{ int x; double y; Pair(int x = 0, double y = 0):x(x), y(y){} bool operator<(const Pair& k)const{ if(y != k.y)return y < k.y; return x < k.x; } }; priority_queue<Pair> Q; int tot, dl1[maxn * 3], dl2[maxn * 3], fr[maxn * 3]; double p[maxn][maxn/10], a[maxn * 3][maxn], b[maxn * 3]; double ans; inline void cal(){ int x = dl1[tot]; for(int i = 1; i <= n; i ++) a[tot][i] = a[tot][i-1]*(1-p[i][x])+a[fr[tot]][i-1]*p[i][x]; //a[tot][i]表示前i个人不选这双袜子的概率 b[tot] = b[fr[tot]] + a[tot] ; //选现在的不选以前的+选以前的不选现在的。 } int main(){ freopen("gift.in", "r", stdin); freopen("gift.out", "w", stdout); scanf("%d%d", &n, &m); int x; for(int i = 1; i <= n; i ++){ for(int j = 1; j <= m; j ++){ scanf("%d", &x); p[i][j] = x / 1000.0; } } for(int i = 1; i <= m; i ++){ dl1[i] = i, dl2[i] = 1, a[i][0] = 1; tot ++; cal(); Q.push(Pair(i, 1 - b[i]));//1-b[i]表示前j只全都送出去的概率 } for(int i = 1; i <= n; i ++){ Pair P = Q.top(); Q.pop(); ans += P.y; tot ++; fr[tot] = P.x; dl1[tot] = dl1[P.x], dl2[tot] = dl2[P.x] + 1; cal(), P.x = tot, P.y = 1 - b[tot], Q.push(P); } printf("%.12lf\n", ans); return 0; }
相关文章推荐
- AndroidSample之CardFlipActivity的学习
- jackson转化报jsonMappingException
- 中缀表达式转后缀表达式
- MPC
- 最简单的Socket通信功能
- IOS开发-Nsstring中搜索方法rangeOfString
- HDOJ--4786--Fibonacci Tree【生成树】
- 一个简单的守护线程示例
- 两个Fragment之间的跳转,和数据的传递
- margin和padding的区别
- reactjs中props和state最佳实践
- Java调用Webservice(asmx)的几个例子
- margin和padding的区别
- Java实现代理模式
- 自己写简单CoreDataManager封装对CoreData操作
- lua手工编译遇到的问题
- jQuery checkbox 保存选中项时除去已经选中项
- struts2 文件超出大小限制后报404错误
- 实现简单的输入编辑,录入正确的字符串,出现‘$’,表示撤销前一个输入,发现连续的‘$’,表示连续撤销前面的输入;发现‘%’,表示放弃前面所有录入;生成最终结果。
- 从jvm编译优化角度解读String的赋值比较