Codeforces183D T-shirt

传送门

这题好神啊……(然而我连每种物品贡献独立都没看出来……

首先$O(n^2 m)$的DP肯定都会写,然后可以发现每种物品一定是选得越多再选一个的收益就越低,因此可以用一个堆维护当前收益最高的物品,每次贪心取收益最高的那个并重新计算贡献……(当然不用堆也行,暴力扫就可以了……)

别问我为什么输出小数点后1000位,我不开心想调戏评测机玩……(然而好像到了一定位数之后就不会再输出了……所以我输出小数点后1亿位但实际上只输出了几百位的样子……

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=3010,maxm=310;
 7 struct A{
 8     int x;
 9     double w;
10     A(int x,double w):x(x),w(w){}
11     bool operator<(const A &a)const{return w<a.w;}
12 };
13 priority_queue<A>heap;
14 double p[maxn][maxm],f[maxn][maxm],g[maxn],ans=0.0;
15 int n,m;
16 int main(){
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
19         scanf("%lf",&p[i][j]);
20         p[i][j]/=1000.0;
21     }
22     for(int j=1;j<=m;j++){
23         for(int i=1;i<=n;i++)f[i][j]=p[i][j]+f[i-1][j]*(1.0-p[i][j]);
24         heap.push(A(j,f[n][j]));
25     }
26     for(int i=1;i<=n;i++){
27         A t=heap.top();
28         heap.pop();
29         ans+=t.w;
30         for(int i=1;i<=n;i++)g[i]=f[i-1][t.x]*p[i][t.x]+g[i-1]*(1-p[i][t.x]);
31         heap.push(A(t.x,g[n]));
32         for(int i=1;i<=n;i++)f[i][t.x]=g[i];
33     }
34     printf("%.1000lf",ans);
35     return 0;
36 }
View Code

 

posted @ 2017-03-20 09:01  AntiLeaf  阅读(131)  评论(0编辑  收藏  举报