UVALive 6514:Crusher’s Code(概率dp)

题目链接 https://icpcarchive.ecs.baylor.edu/external/65/6514.pdf

题意:给出n个数(n<8) 求这n个数分别两个程序排成有序时,程序的期望迭代次数。排序程序如下。

// Monty‘s Code
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‘s Code
while (!sorted(a)) {
    int i = random(n-1) ;
    int j = i + 1 ;
    if (a[i] > a[j])
    swap(a[i], a[j]) ;
}

思路:正常的概率dp。这里“亮”的地方在与,其状态的定义就暴力的定义成了这个串。……因为 8! < 50000。 所以能过。

代码[略锉]:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;

map<int,int> id;
int idp;
int isSortedA;
double e[50000];

int getid(int a) {
    if (id[a] == 0) id[a] = idp++;
    return id[a];
}

int hash(int a[], int n) {
    int ret = 0;
    for (int i = 0; i < n; i++) {
        ret = ret*10 + a[i];
    }
    return ret;
}

int n;

//monty(anow) = p1*monty(anext1) + p2*monty(anext2) + .. + (1-p1-p2)*monty(anow) + 1;
//p = 2/n*n
double monty(int a) {
    if (a == isSortedA) return 0;
    if (e[getid(a)] != 0) return e[getid(a)];

    int tmp[10];
    int tmpa = a;
    for (int i = n-1; i >= 0; i-- ) {
        tmp[i] = tmpa%10;
        tmpa/=10;
    }

    int num = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            if (tmp[i] > tmp[j]) num++;
        }
    }

    if (num == 0) {
        isSortedA = a;
        return 0;
    }

    double ans = n*n/(num*2.0);
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            if (tmp[i] > tmp[j]) {
                swap(tmp[i], tmp[j]);
                ans += 1.0/num * monty(hash(tmp,n));;
                swap(tmp[i], tmp[j]);
            }
        }
    }
    return e[getid(a)] = ans;
}

double carlos(int a) {
    if (a == isSortedA) return 0;
    if (e[getid(a)] != 0) return e[getid(a)];

    int tmp[10];
    int tmpa = a;
    for (int i = n-1; i >= 0; i-- ) {
        tmp[i] = tmpa%10;
        tmpa/=10;
    }

    int num = 0;
    for (int i = 0; i < n-1; i++) {
        if (tmp[i] > tmp[i+1]) num++;
    }

    if (num == 0) {
        isSortedA = a;
        return 0;
    }

    double ans = (n-1.0)/num;
    for (int i = 0; i < n-1; i++) {
        int j = i+1;
        if (tmp[i] > tmp[j]) {
            swap(tmp[i], tmp[j]);
            ans += 1.0/num * carlos(hash(tmp,n));;
            swap(tmp[i], tmp[j]);
        }
    }
    return e[getid(a)] = ans;
}

int a[10];

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {

        isSortedA = -1;

        scanf("%d", &n);
        int tmp[10];
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            tmp[i] = a[i];
        }
        sort(tmp, tmp+n);
        unique(tmp, tmp+n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (a[i] == tmp[j]) {
                    a[i] = j;
                    break;
                }
            }
        }

        idp = 0;
        id.clear();
        memset(e,0,sizeof(e));
        printf("Monty %.6lf ", monty(hash(a,n)));

        idp = 0;
        id.clear();
        memset(e,0,sizeof(e));
        printf("Carlos %.6lf\n", carlos(hash(a,n)));;

    }
    return 0;
}
时间: 2024-08-23 06:01:01

UVALive 6514:Crusher’s Code(概率dp)的相关文章

UVALive 6672 Bonus Cards 概率dp

题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的概率是多少 用acm抢票成功的概率是多少…… 做过不多的概率dp 还在摸索…… dp[i][j]代表第i轮有j个icpc的人已经有票了…… 当然同时i-j个通过其他方式抢票的人也有票了 这就是用同样的函数搜两次的原理…… 优化一次i<=a 一次是把初始化放到for里…… 第一次见这么卡时间的题……

【Foreign】开锁 [概率DP]

开锁 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 4 5 1 2 5 4 3 1 5 2 2 5 4 3 1 5 3 2 5 4 3 1 5 4 2 5 4 3 1 Sample Output 0.000000000 0.600000000 0.900000000 1.000000000 HINT Main idea 一个宝箱内有一个可以开启别的宝箱的钥匙,可以选择k个宝箱,询问能开

POJ1644:To Bet or Not To Bet(概率DP)

Description Alexander Charles McMillan loves to gamble, and during his last trip to the casino he ran across a new game. It is played on a linear sequence of squares as shown below. A chip is initially placed on the Start square. The player then trie

ZOJ3551 Bloodsucker(概率dp)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Bloodsucker Time Limit: 2 Seconds      Memory Limit: 65536 KB In 0th day, there are n-1 people and 1 bloodsucker. Every day, two and only two of them meet. Nothing will happen if they are of

POJ 2096 Collecting Bugs(概率DP求期望)

传送门 Collecting Bugs Time Limit: 10000MS Memory Limit: 64000K Total Submissions: 4333 Accepted: 2151 Case Time Limit: 2000MS Special Judge Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu

atcoderI - Coins ( 概率DP)

I - Coins Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement Let NN be a positive odd number. There are NN coins, numbered 1,2,…,N1,2,…,N. For each ii (1≤i≤N1≤i≤N), when Coin ii is tossed, it comes up heads with probabi

2017 ICPC Asia Urumqi A.coins (概率DP + 期望)

题目链接:Coins Description Alice and Bob are playing a simple game. They line up a row of nn identical coins, all with the heads facing down onto the table and the tails upward. For exactly mm times they select any kk of the coins and toss them into the

Codeforces 28C [概率DP]

/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队伍的期望. 思路: 概率dp dp[i][j][k]代表前i个浴室有j个人最长队伍是k的概率. 枚举第i个浴室的人数.然后转移的时候其实是一个二项分布. */ #include<bits/stdc++.h> using namespace std; int jilu[55]; double dp[

hdu 3076 ssworld VS DDD (概率dp)

///题意: /// A,B掷骰子,对于每一次点数大者胜,平为和,A先胜了m次A赢,B先胜了n次B赢. ///p1表示a赢,p2表示b赢,p=1-p1-p2表示平局 ///a赢得概率 比一次p1 两次p0*p1 三次 p0^2*p1,即A赢的概率为p1+p*p1+p^2*p1+...p^n*p1,n->无穷 ///即a_win=p1/(1-p);b_win=p2/(1-p); ///dp[i][j]表示a赢了j次,b赢了i次的概率 ///dp[i][j]=dp[i-1][j]*b_win+dp[