ZOJ 3822 Domination(2014牡丹江Regional D题)
人家当场切掉的题,表示在场外做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; }