dp水题,dp[i][j][d]表示第d天共有i行,j列被排掉,原来共有m行n列:导出公式:dp[i][j][d]=dp[i-1][j][d-1]*(m-i+1)*)j/(m*n-d+1)+dp[i][j-1][d-1]*(n-j+1)*i/(m*n-d+1)+dp[i-1][j-1][d-1]*(m-i+1)*(n-j+1)/(m*n-d+1)+dp[i][j][d-1]*(i*j-d+1)/(m*n-d+1);
下面是ac代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; double dp[51][51][2501]; int n,m; void init() { for(int i=0;i<=max(m,n);i++) { for(int j=0;j<=(max(m,n))*(max(m,n));j++) { dp[0][i][j]=dp[i][0][j]=0; } } dp[0][0][0]=dp[1][1][1]=1; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&m,&n); init(); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { for(int d=max(i,j);d<=i*j;d++) { double x=(double) (m-i+1),y=(double)(n-j+1),z=(double)(m*n-(d-1)); dp[i][j][d]=dp[i-1][j][d-1]*x*((double) (j))/z+dp[i][j-1][d-1]*y*((double)(i))/z+dp[i-1][j-1][d-1]*x*y/z+dp[i][j][d-1]*((double)(i*j-d+1))/z; } } } double ans=0; for(int i=max(m,n);i<=m*n;i++) { ans+=(dp[m][n][i]-dp[m][n][i-1])*((double)(i)); } printf("%.12lf ",ans); } return 0; }