[CSU 1818 Crusher's Code Submit]记忆化递推

来源:互联网 发布:索尼u盘数据恢复 编辑:程序博客网 时间:2024/05/16 19:52

[CSU 1818 Crusher’s Code Submit]记忆化递推

分类:递推 数学

1. 题目链接

[CSU 1818 Crusher’s Code Submit]

2. 题意描述

有两种随机排序的算法伪代码。现在给你一个长度为N的序列,分别用两种算法进行升序排序。求两种算法的迭代的次数的数学期望,精确到小数点后6位。2N8

3. 解题思路

首先,因为题目给定的状态转移是单向的,也就是说只可能交换两个逆序的元素,不存在状态之间的来回转移。
然后,可以列出状态转移的一个方程。
s表示当前的状态的编号. t表示目标状态的编号,dp[i]就是从当前状态出发到目标状态的期望值。
那么,

  • 对于算法一:
    dp[s]=icnt[(dp[ti]+1)2n2]+[(dp[s]+1)n22cntn2]
  • 对于算法二:
    dp[s]=icnt[(dp[ti]+1)1n1]+[(dp[s]+1)n1cntn1]

然后,移项就可以得到状态转移方程了。

4. 实现代码

#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef long double LB;typedef pair<int, int> PII;typedef pair<LL, LL> PLL;const int INF = 0x3f3f3f3f;const LL INFL = 0x3f3f3f3f3f3f3f3fLL;const LB eps = 1e-6;const int MAXN = 1e3 + 5;int T, N;unordered_map<int, LB> dp[2];unordered_map<int, bool> vis[2];int dst;int Hash(const vector<int>& x) {    int ret = 0;    for(int i = 0; i < N; ++i) {        ret = ret * 8 + x[i];    }    return ret;}LB dfs1(vector<int>& x) {    int v = Hash(x);    if(v == dst) return 0;    if(vis[0][v]) return dp[0][v];    dp[0][v] = 0;    int cnt = 0;    for(int i = 0; i < N; ++i) {        for(int j = i + 1; j < N; ++j) {            if(x[i] <= x[j]) continue;            cnt ++;            swap(x[i], x[j]);            dp[0][v] += (dfs1(x) + 1) * 2;            swap(x[i], x[j]);        }    }    dp[0][v] += N * N - 2 * cnt;    dp[0][v] /= 2 * cnt;    vis[0][v] = true;    return dp[0][v];}LB dfs2(vector<int>& x) {    int v = Hash(x);    if(v == dst) return 0;    if(vis[1][v]) return dp[1][v];    dp[1][v] = 0;    int cnt = 0;    for(int i = 0; i < N - 1; ++i) {        int j = i + 1;        if(x[i] <= x[j]) continue;        cnt ++;        swap(x[i], x[j]);        dp[1][v] += (dfs2(x) + 1);        swap(x[i], x[j]);    }    dp[1][v] += (N - 1 - cnt);    dp[1][v] /= cnt;    vis[1][v] = true;    return dp[1][v];}int main() {#ifdef ___LOCAL_WONZY___    freopen("input.txt", "r", stdin);#endif // ___LOCAL_WONZY___    scanf("%d", &T);    while(T --) {        dp[0].clear(), dp[1].clear();        vis[0].clear(), vis[1].clear();        scanf("%d", &N);        vector<int> a(N), f(N), b(N);        for(int i = 0; i < N; ++i) scanf("%d", &a[i]), f[i] = a[i];        sort(f.begin(), f.end()); f.erase(unique(f.begin(), f.end()), f.end());        for(int i = 0; i < N; ++i) b[i] = a[i] = lower_bound(f.begin(), f.end(), a[i]) - f.begin();        sort(b.begin(), b.end());        dst = Hash(b);        int v = Hash(a);        dfs1(a), dfs2(a);        printf("Monty %.6f Carlos %.6f\n", (double)dp[0][v], (double)dp[1][v]);    }    return 0;}
0 0
原创粉丝点击