CF183D-T-shirtx【dp,贪心】

1|0正题

题目链接:https://www.luogu.com.cn/problem/CF183D


1|1题目大意

n个人,m种衣服,给出每个人喜欢某件衣服的概率,你可以选择n件衣服带过去(可以重复款式)。求最大化能拿到喜欢衣服人的期望数量。

1n3000,1m300


1|2解题思路

考虑暴力的dp,设fi,j,k表示对于前k个人种类为j的衣服选择了i件。

这样显然过不了。

但是考虑答案,假设我们第i种衣服选择了k件那么产生的贡献就是

j=0ki×fi,j,n+kj=k+1nfi,j,n

然后对于k>k+1会多产生的贡献就是1j=1kfi,j,n。考虑到这个值肯定是单调递减的,所以贡献函数是一个关于k的上凸函数。

然后就是很经典的方法了,每次暴力选择一个能扩展的最大的扩展即可。

时间复杂度O(n(n+m))


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=310,N=3100; int n,m,k[M];double s[M],f[2][M][N],a[M][N],ans; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)f[0][i][0]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%lf",&a[j][i]); a[j][i]/=1000.0; f[0][j][i]=f[0][j][i-1]*(1-a[j][i]); } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) f[1][i][j]=f[1][i][j-1]*(1-a[i][j])+f[0][i][j-1]*a[i][j]; k[i]=1;s[i]=f[0][i][n]; } for(int p=1;p<=n;p++){ int pos=1; for(int i=2;i<=m;i++) if(s[i]<s[pos])pos=i; ans=ans+(1-s[pos]); s[pos]=s[pos]+f[k[pos]][pos][n]; k[pos]^=1;int o=k[pos]; for(int i=0;i<=n;i++)f[o][pos][i]=0; for(int i=1;i<=n;i++) f[o][pos][i]=f[o][pos][i-1]*(1-a[pos][i])+f[!o][pos][i-1]*a[pos][i]; } printf("%.12lf\n",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15167034.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(66)  评论(3编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示