Domination


Time Limit: 8 Seconds      Memory Limit: 131072 KB      Special Judge

Edward is the headmaster of Marjar University. He is enthusiastic about chess and often plays chess with his friends. What's more, he bought a large decorative chessboard with N rows and M columns.

Every day after work, Edward will place a chess piece on a random empty cell. A few days later, he found the chessboard was dominated by the chess pieces. That means there is at least one chess piece in every row. Also, there is at least one chess piece in every column.

"That's interesting!" Edward said. He wants to know the expectation number of days to make an empty chessboard of N × M dominated. Please write a program to help him.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There are only two integers N and M (1 <= NM <= 50).

Output

For each test case, output the expectation number of days.

Any solution with a relative or absolute error of at most 10-8 will be accepted.

Sample Input

2
1 3
2 2

Sample Output

3.000000000000
2.666666666667

Author: JIANG, Kai
Source: The 2014 ACM-ICPC Asia Mudanjiang Regional Contest

做了这么多概率dp,结果这道还是没做出来,心情已经不能用郁闷二字来形容了。。。

一、直接求期望

首先是状态的问题,一直在用二维,其实在算概率的时候就应该意识到二维的概率好难算,数据又是50的,很明显要用三维啊!真是笨死了!

dp[i][j][k]代表走了k步,已经有i行,j列安放了棋子。

接下来就是算概率的问题

很明显有四种可转移状态:

1、dp[i][j][k+1]表示走完k+1步,仍是有i行,j列安放了棋子。即安放的第k+1个棋子在i,j所占据的区域,概率为 (i * j - k) / (n * m - k);

2、dp[i][j+1][k+1]表示走完k+1步,有i行,j + 1列安放了棋子。即安放的第k+1个棋子在i行中但不在j列,概率为 i * (m - j) / (n * m - k);

3、dp[i+1][j][k+1]表示走完k+1步,有i + 1行,j列安放了棋子。即安放的第k+1个棋子在j列中但不在i行,概率为 (n - i) * j / (n * m - k);

4、dp[i+1][j+1][k+1]表示走完k+1步,有i + 1行,j + 1列安放了棋子。即安放的第k+1个棋子既不在j列中也不在i行,概率为 (n - i) * (m - j) / (n * m - k);

然后是初始化问题

当i == n && j == m时候,dp[i][j][k] = 0;

无意义的状态全部初始为零,没有影响。

#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(int i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define sfl(n) scanf("%lld", &n)
#define pfi(n) printf("%d\n", n)
#define pfl(n) printf("%lld\n", n)
#define MAXN 55
double dp[MAXN][MAXN][MAXN * MAXN]; int main()
{
int T;
sfi(T);
while(T--)
{
int n, m;
sfi(n), sfi(m);
_cle(dp, );
for(int i = n; i >= ; i--)
for(int j = m; j >= ; j--)
for(int k = i * j; k >= max(i, j); k--)
{
if(n == i && j == m) continue;
dp[i][j][k] += (dp[i][j][k + ] + 1.0) * 1.0 * (i * j - k);
dp[i][j][k] += (dp[i][j + ][k + ] + 1.0) * 1.0 * (i * (m - j));
dp[i][j][k] += (dp[i + ][j][k + ] + 1.0) * 1.0 * (j * (n - i));
dp[i][j][k] += (dp[i + ][j + ][k + ] + 1.0) * 1.0 * ((n - i) * (m - j));
dp[i][j][k] = dp[i][j][k] / (1.0 * (n * m - k));
//printf("%d %d %d : %.12lf\n", i, j, k, dp[i][j][k]);
}
printf("%.12lf\n", dp[][][]);
}
return ;
}

二、先求概率,再求期望

dp[i][j][k]表示放k个棋子达到有i行,j列安放了棋子的概率。

这里有一大误区,就是开始我和我队友都搞错了,结果还以为自己是算的不对,其实是思考错了,就是在算期望是应只考虑真正起作用的棋子,eg:

2 2

dp[2][2][3] = 1, dp[2][2][4] = 1;

其实在放第四颗棋子时就已经必然为两行两列,第四颗棋子已不起作用,放与不放无关痛痒,所以,放第k颗棋子的概率为:

dp[i][j][k] - dp[i][j][k - 1];

#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(int i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define sfl(n) scanf("%lld", &n)
#define pfi(n) printf("%d\n", n)
#define pfl(n) printf("%lld\n", n)
#define MAXN 55
double dp[MAXN][MAXN][MAXN * MAXN]; int main()
{
int T;
sfi(T);
while(T--)
{
int n, m;
sfi(n), sfi(m);
_cle(dp, );
dp[][][] = 1.0;
repu(i, , n + )
repu(j, , m + )
repu(k, max(i, j), i * j + )
{
if(k < ) continue;
dp[i][j][k] += dp[i][j][k - ] * 1.0 * (i * j - k + );
dp[i][j][k] += dp[i - ][j][k - ] * 1.0 * ((n - i + ) * j);
dp[i][j][k] += dp[i][j - ][k - ] * 1.0 * (i * (m - j + ));
dp[i][j][k] += dp[i - ][j - ][k - ] * 1.0 * ((n - i + ) * (m - j + ));
dp[i][j][k] /= (1.0 * (n * m - k + ));
//printf("%d %d %d : %.12lf\n", i, j, k, dp[i][j][k]);
}
double ans = 0.0;
repu(i, max(n, m), n * m + )
ans += (dp[n][m][i] - dp[n][m][i - ]) * 1.0 * i;
printf("%.12lf\n", ans);
//double f = ans * 3.0; }
return ;
}

 

ZOJ 3822(求期望)的更多相关文章

  1. ZOJ 3822 Domination 期望dp

    Domination Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem ...

  2. zoj 3822 Domination(dp)

    题目链接:zoj 3822 Domination 题目大意:给定一个N∗M的棋盘,每次任选一个位置放置一枚棋子,直到每行每列上都至少有一枚棋子,问放置棋子个数的期望. 解题思路:大白书上概率那一张有一 ...

  3. HDU4870_Rating_双号从零单排_高斯消元求期望

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4870 原题: Rating Time Limit: 10000/5000 MS (Java/Other ...

  4. sgu 495. Kids and Prizes (简单概率dp 正推求期望)

    题目链接 495. Kids and Prizes Time limit per test: 0.25 second(s)Memory limit: 262144 kilobytes input: s ...

  5. ZOJ 3822 Domination

    题意: 一个棋盘假设每行每列都有棋子那么这个棋盘达到目标状态  如今随机放棋子  问达到目标状态的期望步数 思路: 用概率来做  计算第k步达到目标状态的概率  进而求期望  概率计算方法就是dp  ...

  6. HDU3853-LOOPS(概率DP求期望)

    LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Total Su ...

  7. HDU 5159 Card (概率求期望)

    B - Card Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Sta ...

  8. Poj 2096 (dp求期望 入门)

    / dp求期望的题. 题意:一个软件有s个子系统,会产生n种bug. 某人一天发现一个bug,这个bug属于某种bug,发生在某个子系统中. 求找到所有的n种bug,且每个子系统都找到bug,这样所要 ...

  9. poj 2096 Collecting Bugs 【概率DP】【逆向递推求期望】

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 3523   Accepted: 1740 ...

随机推荐

  1. sql默认启动密码

    首先启动sqlplus输入用户名:sqlplus / as sysdba密码空缺如果用户被锁定,记得加上SQL> alter user dbsnmp account unlock; User a ...

  2. ServiceStack.OrmLite 笔记10-group having 分页orderby等

    group having 分页等 var ev = OrmLiteConfig.DialectProvider.SqlExpression(); group的使用 同sql一样,注意group分组的字 ...

  3. 自定义NSLog宏输出

    根据编译条件,Debug时输出带行号的日志,Release时关闭日志 /* XCode LLVM XXX - Preprocessing中Debug会添加 DEBUG=1 标志 */ #ifdef D ...

  4. js实现页面传值

    今天做东西用到,在网上查到了这样的一种方法,学习学习: 来源:http://bbs.csdn.net/topics/310229114 Page1: <!DOCTYPE html PUBLIC ...

  5. 详解 ASP.NET异步

    在前文中,介绍了.NET下的多种异步的形式,在WEB程序中,天生就是多线程的,因此使用异步应该更为谨慎.本文将着重展开ASP.NET中的异步. [注意]本文中提到的异步指的是服务器端异步,而非客户端异 ...

  6. 老笔记本_Win7_U盘_ReadyBoost

    老笔记本 Win7 U盘 ReadyBoost 值得尝试

  7. (转)Web自动化测试中的接口测试

    1.背景 1.1 Web程序中的接口 1.1.1 典型的Web设计架构 web是实现了基于网络通信的浏览器客户端与远程服务器进行交互的应用,通常包括两部分:web服务器和web客户端.web客户端的应 ...

  8. Struts1 标签库 说明

    Struts提供了五个标签库,即:HTML.Bean.Logic.Template和Nested. HTML标签 : 用来创建能够和Struts 框架和其他相应的HTML 标签交互的HTML 输入表单 ...

  9. Java源码初学_LinkedHashMap

    一.概述: LinkedHashMap是HashMap的子类,它的基本操作与HashMap相同,与之不同的是,它可以实现按照插入顺序进行排序.也可以通过在构造函数中指定参数,按照访问顺序排序(Link ...

  10. UIButton的常见设置

    - (void)setTitle:(NSString *)title forState:(UIControlState)state;设置按钮的文字 - (void)setTitleColor:(UIC ...