zoj3822 期望dp

每天在一个n*m的棋盘上放棋子,问使得每一行,每一列都有棋子的期望天数

dp[n][m][k] 表示用k个棋子占据了n行,m列,距离目标状态还需要的期望天数

那么dp[n][m][k] = p1 * dp[n][m][k+1] + p2*dp[n+1][m][k+1] + p3*dp[n][m+1][k+1] + p4*dp[n+1][m+1][k+1] + 1

设s= n*m-k, 即剩下多少个地方可以放棋子

p1 = (i*j-k)/s, p1表示放置一棵棋子后,不增加行也不增加列的概率

p2 = (n-i)*j/s, p2表示放置一棵棋子后,只增加行的概率

p3 = (m-j)*i/s,  只增加列的概率

p4 = (n-j)*(m-j)/s , 即增加行又增加列的概率

 

模拟比赛的时候,第三维开小了,只报wa,不报re,这样的情况,发生好多次了

 1 #pragma warning(disable:4996)
 2 #pragma comment(linker, "/STACK:1024000000,1024000000")
 3 #include <iostream>
 4 #include <stdio.h>
 5 #include <string.h>
 6 #include <math.h>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <stack>
10 #include <map>
11 #include <set>
12 #include <string>
13 #include <functional>
14 using namespace std;
15 
16 /*
17 */
18 double dp[55][55][2600];
19 int main()
20 {
21     int N, M, t;
22     scanf("%d", &t);
23     while (t--)
24     {
25         scanf("%d%d", &N, &M);
26         if (N == 1 || M == 1)
27         {
28             printf("%.9lf\n", max(N, M)*1.0);
29             continue;
30         }
31         memset(dp, 0, sizeof(dp));
32         for (int i = N;i >= 0; --i)
33         {
34             for (int j = M;j >= 0; --j)
35             {
36                 if (i == N && j == M) continue;
37                 for (int k = i*j;k >= max(i, j); --k)
38                 {
39                     double s = N*M - k;
40                     dp[i][j][k] = (i*j-k)*1.0/s *dp[i][j][k+1]+(N - i)*j*1.0 / s *dp[i + 1][j][k + 1] + (M - j)*i*1.0 / s*dp[i][j + 1][k + 1] + (N - i)*(M - j)*1.0 / s*dp[i + 1][j + 1][k + 1] + 1;
41                     //printf("%d %d %d \n", i, j, k);
42                 }
43                 
44             }
45         }
46 
47         printf("%.9lf\n", dp[0][0][0]);
48     }
49     return 0;
50 }

 

posted @ 2015-09-10 13:54  justPassBy  阅读(150)  评论(0编辑  收藏  举报