CSU-1818 Crusher’s Code(期望dp)

来源:互联网 发布:程序员用浏览器 编辑:程序博客网 时间:2024/04/28 10:44

1818: Crusher’s Code

        Time Limit: 20 Sec     Memory Limit: 256 Mb     Submitted: 24     Solved: 15    

Description

    Wesley Crusher is the teaching assistant for Introduction to Algorithms. During his first class, the cadets were asked to come up with their own sorting algorithms. Monty came up with the following 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, inspired, came up with the following code:

while (!sorted(a)) {  int i = random(n-1) ;  int j = i + 1 ;  if (a[i] > a[j])     swap(a[i], a[j]) ;}

    Wesley needs to determine which algorithm is better.     For a given input array of up to 8 values, calculate and print the expected number of iterations for each algorithm. That is, on average, how many iterations should each algorithm take for the given input?

Input

The first line contains T, the number of test cases: 2 ≤ T ≤ 100.     Each test case is given on a single line. The first value is N, the number of array elements; 2 ≤ N ≤ 8. This is followed on the same line by N integer array elements. The array elements will have values between 0 and 100 inclusive. The array elements may not be distinct.

Output

For each test case, print out the expected number of iterations for Monty’s algorithm and for Carlos’s algorithm, as shown in the sample output section. There should be exactly one space between words and no spaces at the start of each line or at the end of each line. There should be exactly six digits after the decimal point. Rounding should be to nearest representable value.

Sample Input

122 1 22 2 13 1 2 33 3 2 14 1 2 3 44 4 3 2 14 2 1 4 35 1 1 1 1 15 5 4 3 2 18 8 7 6 5 4 3 2 18 3 1 4 1 5 9 2 68 2 7 1 8 2 8 1 8

Sample Output

Monty 0.000000 Carlos 0.000000Monty 2.000000 Carlos 1.000000Monty 0.000000 Carlos 0.000000Monty 6.000000 Carlos 5.000000Monty 0.000000 Carlos 0.000000Monty 14.666667 Carlos 12.500000Monty 12.000000 Carlos 4.500000Monty 0.000000 Carlos 0.000000Monty 26.382275 Carlos 23.641975Monty 89.576273 Carlos 79.496510Monty 79.161905 Carlos 33.422840Monty 63.815873 Carlos 38.910494
题意:有2种排序方法:①随机选取i,j∈[1,n],如果A[min(i,j)]>A[max(i,j)],则进行交换;②随机选取i∈[1,n-1],如果A[i]>A[i+1],则进行交换
要求分别求出使用2种排序方法排序成功的操作期望


题解:期望dp+hash+状压
考虑到n<=8,因此对于A[i]可以按从小到大映射为[0,7],对于不同的排序最多有8!种状态,于是就能想到用状压。
对于方法①:dp[now_S]=∑dp[next_S]/success ,success∈[0,n^2]
对于方法②:dp[now_S]=∑dp[next_S]/success ,success∈[0,n-1]
其中success为当前状态能成功的(i,j)的取值种类


#include<bits/stdc++.h>using namespace std;int n;int A[10];void init(){    int B[10],v[105],sz=0;    memcpy(B,A,sizeof(A));    memset(v,-1,sizeof(v));    sort(B,B+n);    for(int i=0;i<n;i++)        if(v[B[i]]==-1) v[B[i]]=sz++;    for(int i=0;i<n;i++) {        A[i]=v[A[i]];    }}int get_sta(int A[]){    int ret=0;    for(int i=0;i<n;i++) ret=ret*8+A[i];    return ret;}void get_arr(int S,int A[]){    for(int i=n-1;i>=0;i--){        A[i]=S%8;        S/=8;    }}const int MX = 1e5 + 5;map<int,int>vis;int sz,S[MX];void bfs(int s){    vis.clear();    queue<int>q;    q.push(s);    vis[s]=1;    while(!q.empty()){        int u=q.front();q.pop();        get_arr(u,A);        for(int i=0;i<n;i++)            for(int j=i+1;j<n;j++)                if(A[i]>A[j]){                    swap(A[i],A[j]);                    int SS=get_sta(A);                    if(vis[SS]==0){                        q.push(SS);                        vis[SS]=1;                    }                    swap(A[i],A[j]);                }    }    sz=0;    for(map<int,int>::iterator it=vis.begin();it!=vis.end();it++) {        S[sz]=it->first;        it->second=sz++;    }}double dp[MX];//递推写法double DP1(){    memset(dp,0,sizeof(dp));    for(int k=0;k<sz;k++){        int success=0;        int sta=S[k];        get_arr(sta,A);        for(int i=0;i<n;i++)            for(int j=0;j<n;j++){                int l=min(i,j),r=max(i,j);                if(A[l]>A[r]){                    swap(A[l],A[r]);                    int SS=get_sta(A);                    success++;                    dp[k]+=dp[vis[SS]]/(n*n);                    swap(A[l],A[r]);                }            }        if(success>0) dp[k]=(dp[k]+1)*n*n/success;    }    return dp[sz-1];}double DP2(){    memset(dp,0,sizeof(dp));    for(int k=0;k<sz;k++){        int success=0;        int sta=S[k];        get_arr(sta,A);        for(int l=0;l<n-1;l++){            int r=l+1;            if(A[l]>A[r]){                swap(A[l],A[r]);                int SS=get_sta(A);                success++;                dp[k]+=dp[vis[SS]]/(n-1);                swap(A[l],A[r]);            }        }        if(success>0) dp[k]=(dp[k]+1)*(n-1)/success;    }    return dp[sz-1];}//记忆化搜索写法double DP1(int u){    if(u==0) return dp[u]=0;    if(dp[u]>=0) return dp[u];    int sta=S[u];    get_arr(sta,A);    int success=0;    dp[u]=0;    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            int l=min(i,j),r=max(i,j);            if(A[l]>A[r]){                swap(A[l],A[r]);                int SS=get_sta(A);                success++;                dp[u]+=DP1(vis[SS])/(n*n);                swap(A[l],A[r]);            }        }    }    if(success>0) dp[u]=(dp[u]+1)*n*n/success;    return dp[u];}double DP2(int u){    if(u==0) return dp[u]=0;    if(dp[u]>=0) return dp[u];    int sta=S[u];    get_arr(sta,A);    int success=0;    dp[u]=0;    for(int i=0;i<n-1;i++){        int l=i,r=i+1;        if(A[l]>A[r]){            swap(A[l],A[r]);            int SS=get_sta(A);            success++;            dp[u]+=DP2(vis[SS])/(n-1);            swap(A[l],A[r]);        }    }    if(success>0) dp[u]=(dp[u]+1)*(n-1)/success;    return dp[u];}int main(){    int T;    //freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        scanf("%d",&n);        for(int i=0;i<n;i++) scanf("%d",&A[i]);        init();        int init_sta=get_sta(A);        bfs(init_sta);        for(int i=0;i<sz;i++) dp[i]=0;        double ans1=DP1();        for(int i=0;i<sz;i++) dp[i]=0;        double ans2=DP2();        printf("Monty %.6f Carlos %.6f\n",ans1,ans2);    }    return 0;}



0 0
原创粉丝点击