ZOJ 3822 (2014 Mudanjiang D regional tournament title) (probability dp)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5376

Meaning of the questions: each row to n * m on the board every day to put a pawn, the board can ask how many days each column has at least a pawn expectations

 

Analysis: We analyze the wave; explain my weak weak problem-solving ideas

(1) First, it is conceivable to set up a dp [val] represents the current val spent a few days there is a probability flag from the target state. But we can find a simple state val is not accurate status shown , for example, now I know just how much the use of the flag, not currently know how many rows and columns there is a flag;

(2) so we changed to dp dp [val] [i] [j] is represented by a flag of val, there i rows and j columns with flags, and a few days to a target state of probability. Note that we set the probability dp [val] [i] [ j] is a state val few days, so we can put 3 seek out the probability, and finally calculate the expected

(3) state transition: There are four states

(1) is added to a record in rows and columns: dp [val + 1] [i] [j] -> dp [val] [i] [j] * p1;

(2) is added in a row he had not recorded in the recording through the column: dp [val + 1] [i + 1] [j] -> dp [val] [i] [j] * p2;

(3) adding a record is placed over the row and column had no record of: dp [val + 1] [i] [j + 1] -> dp [val] [i] [j] * p3;

(4) is added in a row and column not recorded not recorded over in: dp [val + 1] [i + 1] [j + 1] -> dp [val] [i] [j] * p4;

p1, p2, p3, p4 can be observed that the method for finding FIG:

The red areas j rows and k columns can be considered to have at least a piece of

 

 

#include<bits/stdc++.h>
using namespace std;
double dp[2501][51][51];
int main() {
    int t;
    cin >> t;
    int k=1;
    while(t--) {
      int n,m;scanf("%d%d",&n,&m);
      memset(dp,0,sizeof(dp));
      dp[1][1][1]=1;
      for(int val=1 ; val<n*m ; val++) ///放其
      {
          for(int i=1 ; i<=n ; i++)
            {
                for(int j=1 ; j<=m ; j++)
                {
                    if(dp[val][i][j]==0) continue;
                    double p1,p2,p3,p4;
                    if( i<n  ||j<m){
                    p1=(i*j-val)*1.0/(n*m-val);
                    dp[val+1][i][j]+=dp[val][i][j]*p1;
                    }
                    p2=j*(n-i)*1.0/(n*m-val);
                    dp[val+1][i+1][j]+=dp[val][i][j]*p2;
                    p3=i*(m-j)*1.0/(n*m-val);
                    dp[val+1][i][j+1]+=dp[val][i][j]*p3;
                    p4=(n-i)*(m-j)*1.0/(n*m-val);
                    dp[val+1][i+1][j+1]+=dp[val][i][j]*p4;

                }
            }
      }
      double ans=0;
      for(int val=1 ; val<=n*m ; val++)
      {
          ans+=dp[val][n][m]*val;
          //cout<<dp[val][n][m]<<endl;
      }
      printf("%.12f\n",ans);

    }
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/shuaihui520/p/11165758.html