[CF183D]T-shirt

题目大意:

有\(n(n\le3000)\)个人和\(m(m\le300)\)种T恤,每个人都有一种喜欢的T恤,你知道每个人喜欢每种T恤的概率\(p_{i,j}\)。

请你选定\(n\)件体恤的种类,人们会按照编号从\(1\sim n\)挑选T恤,如果剩下还有他喜欢的,则会选走,否则不变。

求送出T恤件数的最大期望。

思路:

用\(f[i][j][k]\)表示对于第\(i\)件T恤,前\(j\)个人中有\(k\)个人喜欢的概率。\(g[i][j]\)表示对于第\(i\)种T恤,选取\(j\)件时对答案贡献的期望值。

\(f\)的转移方程显然,同时也不难得到\(g\)的状态转移方程:

\[g[i][j]=\sum_{k=0}^jk\cdot f[i][n][k]+\sum_{k=j+1}^nj\cdot f[i][n][k]
\]

这样的动态规划是\(\mathcal O(nm^2)\)的。

考虑优化,对\(g\)的相邻两项作差,得到:

\[g[i][j+1]-g[i][j]=1-\sum_{k=0}^j f[i][n][k]
\]

显然这个差值\(\Delta\)表示再加入一条这样的T恤对答案的贡献,而它又是单调递减的,因此每次选取最大的\(\Delta\)更新一定最优。

一开始只计算\(f[i][j][0]\)和\(\Delta[i][0]\),然后每次选取\(\Delta\)最大的T恤更新答案,然后对相应的T恤进行更新\(f\)和\(\Delta\)即可。这样可以同时省掉\(f\)的第三维。

时间复杂度\(\mathcal O(nm+n^2)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=3001,M=301;
double p[N][M],f[M][N],del[M];
//f[i][j]: 第i种衣服前j个人有cnt[i]个人喜欢的概率
//del[i]: 新加入第i种衣服对答案的贡献
int main() {
const int n=getint(),m=getint();
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
p[i][j]=getint()/1000.;
}
}
for(register int i=1;i<=m;i++) {
f[i][0]=1;
for(register int j=1;j<=n;j++) {
f[i][j]=f[i][j-1]*(1-p[j][i]);
}
del[i]=1-f[i][n];
}
double ans=0;
for(register int i=0;i<n;i++) {
const int k=std::max_element(&del[1],&del[m]+1)-del;
ans+=del[k];
for(register int i=n;i>=1;i--) {
f[k][i]=f[k][i-1]*p[i][k];
}
f[k][0]=0;
for(register int i=2;i<=n;i++) {
f[k][i]+=f[k][i-1]*(1-p[i][k]);
}
del[k]-=f[k][n];
}
printf("%.12f\n",ans);
return 0;
}

[CF183D]T-shirt的更多相关文章

  1. 新概念英语(1-11)Is this your shirt ?

    Is this your shirt?Whose shirt is white? A:Whose shirt is that? Is this your shirt, Dave? Dave:No si ...

  2. Windows 10文件夹Shirt+鼠标右键出现“在此处打开命令窗口”

    Windows 10文件夹Shirt+鼠标右键出现“在此处打开命令窗口” Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directo ...

  3. 【CF183D】T-shirt(动态规划,贪心)

    [CF183D]T-shirt(动态规划,贪心) 题面 洛谷 CodeForces 题解 \(O(n^2m)\)的暴力懒得写了,比较容易,可以自己想想. 做法是这样的,首先我们发现一个结论: 对于某个 ...

  4. SELECT s.* FROM person p INNER JOIN shirt s ON s.owner = p.id WHERE p.name LIKE 'Lilliana%' AND s.color <> 'white';

    SELECT s.* FROM person p INNER JOIN shirt sON s.owner = p.idWHERE p.name LIKE 'Lilliana%'AND s.color ...

  5. [Eclipse插件] Eclipse设置Tab键为空格(ctrl+shirt+f格式化生效)!

    自定义format格式,用空格替换Tab键,ctrl+shit+f格式化后生效: 设置Eclipse中按Tab键为4个空格,这里标记下! Window-->Preferences-->Ja ...

  6. javascript arguments(转)

    什么是arguments arguments 是是JavaScript里的一个内置对象,它很古怪,也经常被人所忽视,但实际上是很重要的.所有主要的js函数库都利用了arguments对象.所以agru ...

  7. Linux.NET实战手记—自己动手改泥鳅(下)

    在上回合中,我们不痛不痒的把小泥鳅的数据库从只能供在Windows下运行的Access数据库改为支持跨平台的MYSQL数据库,毫无营养的修改,本回合中,我们将把我们修改后得来的项目往Linux中部署. ...

  8. MySQL基础

    数据库操作 ---终端使用数据库 mysql -u root -p 之后回车键 输入密码 ---显示所有数据库: show databases; ---默认数据库: mysql - 用户权限相关数据 ...

  9. Swift3.0P1 语法指南——构造器

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

随机推荐

  1. UNIX环境高级编程 第5章 标准I/O库

    本章是关于C语言标准I/O库的,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系.由于UNIX系统存在很多实现,而每个实现都有自己的标准I/O库,为了统一 ...

  2. python程序练习题集

    1.#输入a,b,c,d4个整数,计算a+b-c*d的结果 a=input("please input a nimber:") b=input("please input ...

  3. Redis简介——(一)

    1.关于关系型数据库和nosql数据库 关系型数据库是基于关系表的数据库,最终会将数据持久化到磁盘上,而nosql数据 库是基于特殊的结构,并将数据存储到内存的数据库.从性能上而言,nosql数据库 ...

  4. 【连接查询】mySql多表连接查询与union与union all用法

    1.准备两个表 表a: 结构: mysql> desc a; +-------+-------------+------+-----+---------+-------+ | Field | T ...

  5. 我应该记录一下我不太了解的一些c语言函数

    当然,现在还不分类 fmemopen getpagesize()

  6. AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision

    题目传送门:ARC090E. 题意简述: 给定一张有 \(N\) 个点 \(M\) 条边的无向图.每条边有相应的边权,边权是正整数. 小 A 要从结点 \(S\) 走到结点 \(T\) ,而小 B 则 ...

  7. 彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)[转]

    最近有一些朋友常问我一些乱码的问题,和他们交流过程中,发现这个编码的相关知识还真是杂乱不堪,不少人对一些知识理解似乎也有些偏差,网上百度, google的内容,也有不少以讹传讹,根本就是错误的(例如说 ...

  8. Tomcat安装与优化

    Tomcat安装与优化 1.安装jdk环境 最新的JDK下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downlo ...

  9. 【C语言学习笔记】字符串拼接的3种方法 .

    昨天晚上和@buptpatriot讨论函数返回指针(malloc生成的)的问题,提到字符串拼接,做个总结. #include<stdio.h> #include<stdlib.h&g ...

  10. linux文件处理

    取中间的行数作为train.txt sed -n '1000000,170910580p' train.txt > trainv1.txt 取前面的行数作为dev.txt head -10000 ...