题意:
有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);
}
}