codeforces 183d(期望概率dp)
2017-09-14 20:11
337 查看
我还是在noip模拟看到这题,看起来就是dp,然而考试时并想不到正解,打暴力居然MLE。dp又不会做……
然后我用了一个上午才YY了出来。
题面
题目描述
你要给N个人准备礼物——T-shirt!但是你不知道他们的尺码……总共有M种尺码,编号从1到M。虽然你不记得每个人准确的尺码,但是你记得对于每一个人i,每一个尺码j,i的尺码正好是j的概率Pij.
现在你要买正好N件T-shirt,求能收到合适尺码礼物的人数的最大期望值。
你送礼物的方式是:从第1个人到第N个人依次询问,如果还有他们的尺码的T-shirt,就送出,否则就不送。
输入格式
第一行有两个整数N,M
接下来有N行,每行有M个整数,第i行的第j个整数表示Pij,用0到1000的整数表示,真实的概率用给出的数字除以1000得到。
保证每一行的整数和是1000。
输出格式
一个实数,即最大期望保留8位小数。
数据范围
50%的数据:1<=n<=500,1<=m<=100
100%的数据:1<=n<=3000,1<=m<=300
缘于我对期望的直觉,我觉得不同T-shirt之间是相互独立的,即对于每件T-shirt,你买多少件,就会产生固定的期望。不同T-shirt产生的期望是可以相加的。
看出了这一点,就可以想暴力了。
由于买多少件,就会产生固定的期望、一共买n件,所以核心算法应该是个分组背包。
所以我们就要求出每件物品,买1~n件分别的期望。
根据期望=概率*件数,对于第k件T-shirt,故我们设f[i][j]表示,假设你买了无限件,在前i个人,能送出j件的概率。
根据字面意思转移,有f[i][j]=f[i−1][j−1]∗a[i][k]+f[i−1][j]∗(1−a[i][k])
设g[i]表示买i件送出件数的期望值,有g[i]=∑j=0ij∗f[n][j]+i∗∑j=i+1nf[n][j]
可以前缀和优化成O(n)
然后就是一个分组背包了。
这样复杂度是O(n^2*m),MLE的问题可以用滚动数组解决。
我们观察g数组,直觉告诉我们它是个上凸函数,在送礼物给小姐姐时,你送多少和她的美滋滋程度显然不是正比的,证明的话,通过一轮画柿子,就有g[k+1]−g[k]=1−∑i=0kf[n][i]
这个显然是单调的,所以就是上凸的了。
所以若g[i]不选,就不会选g[i+1],所以选一个算一个就可以了。
复杂度O(n^2+nm)。
即使我们手中空无一物,却能因此紧紧相牵。
然后我用了一个上午才YY了出来。
题面
题目描述
你要给N个人准备礼物——T-shirt!但是你不知道他们的尺码……总共有M种尺码,编号从1到M。虽然你不记得每个人准确的尺码,但是你记得对于每一个人i,每一个尺码j,i的尺码正好是j的概率Pij.
现在你要买正好N件T-shirt,求能收到合适尺码礼物的人数的最大期望值。
你送礼物的方式是:从第1个人到第N个人依次询问,如果还有他们的尺码的T-shirt,就送出,否则就不送。
输入格式
第一行有两个整数N,M
接下来有N行,每行有M个整数,第i行的第j个整数表示Pij,用0到1000的整数表示,真实的概率用给出的数字除以1000得到。
保证每一行的整数和是1000。
输出格式
一个实数,即最大期望保留8位小数。
数据范围
50%的数据:1<=n<=500,1<=m<=100
100%的数据:1<=n<=3000,1<=m<=300
缘于我对期望的直觉,我觉得不同T-shirt之间是相互独立的,即对于每件T-shirt,你买多少件,就会产生固定的期望。不同T-shirt产生的期望是可以相加的。
看出了这一点,就可以想暴力了。
由于买多少件,就会产生固定的期望、一共买n件,所以核心算法应该是个分组背包。
所以我们就要求出每件物品,买1~n件分别的期望。
根据期望=概率*件数,对于第k件T-shirt,故我们设f[i][j]表示,假设你买了无限件,在前i个人,能送出j件的概率。
根据字面意思转移,有f[i][j]=f[i−1][j−1]∗a[i][k]+f[i−1][j]∗(1−a[i][k])
设g[i]表示买i件送出件数的期望值,有g[i]=∑j=0ij∗f[n][j]+i∗∑j=i+1nf[n][j]
可以前缀和优化成O(n)
然后就是一个分组背包了。
这样复杂度是O(n^2*m),MLE的问题可以用滚动数组解决。
我们观察g数组,直觉告诉我们它是个上凸函数,在送礼物给小姐姐时,你送多少和她的美滋滋程度显然不是正比的,证明的话,通过一轮画柿子,就有g[k+1]−g[k]=1−∑i=0kf[n][i]
这个显然是单调的,所以就是上凸的了。
所以若g[i]不选,就不会选g[i+1],所以选一个算一个就可以了。
复杂度O(n^2+nm)。
#include <iostream> #include <fstream> #include <algorithm> #include <cmath> #include <ctime> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; #define mmst(a, b) memset(a, b, sizeof(a)) #define mmcp(a, b) memcpy(a, b, sizeof(b)) typedef long long LL; const int N=3030; int n,m; int a ; int num[330]; double f[330] ,g[330],h ,sum[330],gl ,last[330],ans; void work(int x) { num[x]++; if(num[x]>n) { g[x]=0; return; } for(int i=0;i<=n;i++) h[i]=f[x][i]; f[x][0]=0.0; for(int i=1;i<=n;i++) f[x][i]=f[x][i-1]*(1000.0-1.0*a[i][x])/1000.0+h[i-1]*1.0*a[i][x]/1000.0; gl[x]+=f[x] ; sum[x]+=f[x] *num[x]; double now=sum[x]+(num[x]+1)*(1.0-gl[x]); g[x]=now-last[x]; last[x]=now; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int ii=1;ii<=m;ii++) { f[ii][0]=1.0; for(int i=1;i<=n;i++) f[ii][i]=f[ii][i-1]*(1000.0-1.0*a[i][ii])/1000.0; gl[ii]=f[ii] ; last[ii]=g[ii]=1.0-f[ii] ; } for(int i=1;i<=n;i++) { double mx=0.0,tu; for(int ii=1;ii<=m;ii++) if(g[ii]>mx) { mx=g[ii]; tu=ii; } ans+=mx; work(tu); } printf("%.8lf",ans); return 0; }
即使我们手中空无一物,却能因此紧紧相牵。
相关文章推荐
- codeforces 16E Fish (概率-期望DP)
- Codeforces 280C Game on Tree 概率dp 树上随机删子树 求删完次数的期望
- Codeforces 696B. Puzzles (概率DP求期望)
- CodeForces 167B - Wizards and Huge Prize 期望概率dp
- BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元
- Codeforces 839C Journey (树形dp + 概率期望)
- codeforces 698 C. LRU (概率与期望+状压DP)
- Codeforces 513C Second price auction 概率dp 求期望
- Codeforces 518D 概率DP
- poj3071Football(概率期望dp)
- POJ 2096 Collecting Bugs(概率DP求期望)
- 期望&概率dp总结
- hdu 3853 LOOPS (概率dp 逆推求期望)
- LightOJ 1030 【概率DP求期望】
- CodeForces 148D Bag of mice —— 概率DP
- [HDU4336]Card Collector(概率期望+状压dp)
- SDUT 飞行棋 (概率DP & 期望)
- Codeforces 148D. Bag of mice(概率DP)
- Codeforces 768D Jon and Orbs【概率Dp】
- HDU 4405 Aeroplane chess(概率DP求期望)