Find the Marble ZOJ

来源:互联网 发布:spss数据统计分析 编辑:程序博客网 时间:2024/05/21 12:45

题意:

有n个pots,其中只有第s个pots中有marble,进行m次交换,小明只看到k次交换,问他最有可能猜marble在哪个位置的pots上?


代码:

推发生概率,可以转换成对情况数的统计,哪种情况多说明哪种概率大。

用动态规划可以统计出来。

dp[i][j][k]分别表示前i次交换看到j次marble在第k个pots的情况数量。

转移方程大概不难想,但是细节要注意下。

假设当前交换了x和y,对于x、y来说转移方程为

dp[i][j][x]=dp[i-1][j][x]+dp[i-1][j-1][y],dp[i][j][y]=dp[i-1][j][y]+dp[i-1][j-1][x].

对于x和y之外的其它位置,转移方程为

dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k];

dp[i-1][j][k]好理解,继承上一次交换是就看到了j次落在k位置的情况,对于每个位置来说都是一样的,然后对于x和y来说,从dp[i-1][j-1]的情况转移到dp[i][j]的话说明看到了当前这次交换,那么应该继承要交换位置的情况,而对于其他位置来说,虽然看到了交换,但是与自己无关,所以仍然继承自己位置的情况。


要注意的细节问题是,dp[i][0][s]=1对于0<=i<=m都要初始化为1,含义容易想。


代码:

#include <bits/stdc++.h>using namespace std;long long dp[55][55][55];int x, y;int use(int u){    if(u==x)return y;    if(u==y)return x;    return u;}int main(){    int  i, j, t, n, m, k, s;    cin>>t;    while(t--)    {        memset(dp, 0, sizeof(dp));        scanf("%d%d%d%d", &n, &m, &k, &s);        for(i=0; i<=m; i++)dp[i][0][s]=1;        for(i=1; i<=m; i++)        {            scanf("%d%d", &x, &y);            for(j=1; j<=min(k, i); j++)            {               for(int e=1; e<=n; e++)               {           //      if(e==x || e==y)continue;                 dp[i][j][e]=dp[i-1][j][e]+dp[i-1][j-1][e];               }                dp[i][j][x]=dp[i-1][j][x]+dp[i-1][j-1][y];                dp[i][j][y]=dp[i-1][j][y]+dp[i-1][j-1][x];                //dp[i][j][y]+=dp[i-1][j-1][y];                //printf("i%d j%d %lld %lld\n", i, j,  dp[i][j][x], dp[i][j][y]);                //dp[i][j][x]+=dp[i-1][j-1][x];               // printf("i%d j%d %lld %lld\n", i, j,  dp[i][j][x], dp[i][j][y]);            }                  }        j=1;        for(i=1; i<=n; i++)        {            if(dp[m][k][i]>dp[m][k][j])j=i;        }        printf("%d\n", j);    }}



0 0