人家当场切掉的题,表示在场外做zoj还是要别人提醒dp数组的i,j,k分别表示什么含义才能AC...
下周鞍山之行无限堪忧TAT~
题目大意:有一个n * m的棋盘,每天放入一个棋子,当所有行和列都存在棋子的时候,就是一种符合的情况。
然后这种情况的值就是它的天数(也就是棋子个数),问所有符合的情况的期望值。
dp[i][j][k]表示放i个棋子,能盖住j行k列的概率。
由dp[i-1]也就是放i-1个棋子来推的话,如下图:
由这四种情况所推得的即为新的dp[i]。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
double dp[3000][55][55];
int t, n, m;
void init() {
memset(dp, 0, sizeof(dp));
dp[0][0][0] = 1.0;
}
int main() {
scanf("%d", &t);
while(t--) {
init();
scanf("%d%d", &n, &m);
if(n < m) swap(n, m);
int max_day = n * m - m + 1;
for(int i = 1; i <= max_day; i++) {
for(int j = 1; j <= i && j <= n; j++) {
for(int k = 1; k <= i && k <= m; k++) {
if(j == n && k == m) {
dp[i][j][k] = dp[i-1][j-1][k-1]*(double)(n-j+1)*(double)(m-k+1)/(double)(n*m-i+1)
+ dp[i-1][j][k-1]*(double)((m-k+1)*j)/(double)(n*m-i+1)
+ dp[i-1][j-1][k]*(double)((n-j+1)*k)/(double)(n*m-i+1);
} else {
dp[i][j][k] = dp[i-1][j-1][k-1]*(double)(n-j+1)*(double)(m-k+1)/(double)(n*m-i+1)
+ dp[i-1][j][k-1]*(double)((m-k+1)*j)/(double)(n*m-i+1)
+ dp[i-1][j-1][k]*(double)((n-j+1)*k)/(double)(n*m-i+1)
+ dp[i-1][j][k]*((double)(j*k)-(i-1))/(double)(n*m-i+1);
}
}
}
}
double ans = 0.0;
for(int i = 1; i <= max_day; i++) {
ans += double(i) * dp[i][n][m];
}
printf("%.10lf\n", ans);
}
return 0;
}