题意(翻译润色了一下):
^▽^神秘的三角洲一直流传着一个关于排序的问题。
你在旅途中遇到了Monly和Carlos,他们都对自己解决这个问题的方案很有信心。
Monty的代码是这样的:
while (!sorted(a)) {
int i = random(n) ;
int j = random(n) ;
if (a[min(i,j)] > a[max(i,j)])
swap(a[i], a[j]) ;
}
这是Carlos的代码:
while (!sorted(a)) {
int i = random(n-1) ;
int j = i + 1 ;
if (a[i] > a[j])
swap(a[i], a[j]) ;
}
请聪明的你帮争论不休的他们确定哪种算法更好。
数组最长为8,计算两种算法在给定的序列情况下,完成排序需要迭代次数的期望。
思路:
由于最大长度只有8,可以想到把这个序列hash成一个整数。当它变成12345……这样的数字的时候就排序完成了。记忆化搜索or迭代递推都行。
现在要求期望,一般求期望都是倒推。
那么当前的状态now,必定由它换位置可以转移到的所有情况next状态的期望各自*概率,再加上它自己原封不动的期望*不动的概率(因为有可能不交换),最后+1表示过了一回合。也就是说公式为下图橙色的那部分。推导见蓝色部分,+1写里面外面都一样,详情见图。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<unordered_map>
using namespace std;
const int maxv = 20;
int T, n, gi[maxv], a[maxv], A;
map<int, double>mp;
int hs(int x[])
{
int res = 0;
for (int i = 1; i <= n; i++)
{
res = res * 8 + x[i];
}
return res;
}
double dfs1(int *x)
{
int nows = hs(x);
if (nows == A)
return 0;
if (mp.find(nows) != mp.end())
{
return mp[nows];
}
double sum = 0;
int c = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int s = min(i, j);
int b = max(i, j);
if (x[s] > x[b])
{
c++;
swap(x[s], x[b]);
sum += dfs1(x);
swap(x[s], x[b]);
}
}
}
sum += (n*n - c);
sum /= c;
return mp[nows] = sum + 1.0;
}
double dfs2(int *x)
{
int nows = hs(x);
if (nows == A)
return 0;
if (mp.find(nows) != mp.end())
{
return mp[nows];
}
int c = 0;
double sum = 0;
for (int i = 1; i <= n - 1; i++)
{
int j = i + 1;
if (x[i] > x[j])
{
c++;
swap(x[i], x[j]);
sum += dfs2(x);
swap(x[i], x[j]);
}
}
sum += n - 1 - c;
sum /= c;
return mp[nows] = sum + 1.0;
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &gi[i]);
a[i] = gi[i];
}
sort(a + 1, a + 1 + n);
int num = unique(a + 1, a + 1 + n) - a - 1;
for (int i = 1; i <= n; i++)
{
gi[i] = lower_bound(a + 1, a + 1 + num, gi[i]) - a;
}
for (int i = 1; i <= n; i++)
a[i] = gi[i];
sort(a + 1, a + 1 + n);
A = hs(a);
mp.clear();
double A1 = dfs1(gi);
mp.clear();
double A2 = dfs2(gi);
printf("Monty %.6lf Carlos %.6lf\n", A1, A2);
}
return 0;
}