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 <= N, M <= 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. TestNg测试框架使用笔记

    Gradle支持TestNG test { useTestNG(){ //指定testng配置文件 suites(file('src/test/resources/testng.xml')) } } ...

  2. Codeforces Round #375 (Div. 2) D. Lakes in Berland dfs

    D. Lakes in Berland time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. Windows Internals学习笔记(四)Trap Dispatching

    参考资料: 1. <Windows Internals> 知识点: ● 陷阱trap:它是一种处理器机制,用以在某一异常或中断出现时,捕捉该执行线程,并将其控制权转交到操作系统中某一固定位 ...

  4. 《Linux内核设计的艺术》学习笔记(五)INT 0x10中断

    参考书籍: 1. <IBM-PC汇编语言程序设计> 2. http://www.ctyme.com/intr/int-10.htm   ◆ 设置显示方式: 功能号:AH = 00H 调用参 ...

  5. 前端代码新写法——Zen Coding

    是不是还在为html繁琐的标签写法而苦恼? 是不是还在枯燥的写尖括号? Zen Coding的到来将让前端编码不在繁琐.不再拘泥html的尖括号和一堆一堆的标签. 先看看ZenCoding的效果图. ...

  6. Git学习(1)Git 简介

    Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件. Git ...

  7. Maven核心概念之依赖,聚合与继承

    一.依赖 我们项目中依赖的jar包可以通过依赖的方式(dependencies元素下添加dependency子元素)引入. <dependency> <groupId>juni ...

  8. Oracle冷备份及其恢复

    一. 冷备份的概念 冷备份是指在数据库关闭状态下所做的物理拷贝,也称脱机备份. 适合于非归档模式下的备份,而且也只能采用这种方式备份. 二. 需要备份的文件 必须备份的文件: 数据文件和控制文件 可以 ...

  9. Mysql插入数据的时候,中文乱码问题的解决

    如果在Mysql中插入数据的时候,没有特定指定编码,可能会产生一系列的问题,例如,如果用insert语句的时候,可能提示incorrect values,等...究其原因,实际上无非是要让数据库和表中 ...

  10. arr.sort()排序方法

    <!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8&qu ...