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: 15Description
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种排序方法排序成功的操作期望
题解:期望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;}
- CSU-1818 Crusher’s Code(期望dp)
- [CSU 1818 Crusher's Code Submit]记忆化递推
- CSU 1690 期望DP + 数据结构
- URAL 1831|Tsyfirkin's Lesson|期望DP
- 【DP】 csu 1620 A Cure for the Common Code
- URAL 1994 The Emperor's plan(dp、期望)
- [Codeforces235B]Let's Play Osu!(期望dp)
- bzoj3470 Freda's Walk (期望概率DP)
- DP期望
- 期望DP
- 期望DP
- 期望dp
- 期望DP
- CSU 1620: A Cure for the Common Code(KMP+区间DP)
- CSU 1620: A Cure for the Common Code (区间DP KMP预处理)
- CSU 1620 A Cure for the Common Code (HASH+区间DP)
- Timo's mushrooms CSU
- CSU 1529 Equator DP
- POJ 3368 Frequent values(RMQ/线段树区间合并)
- 痴情人肠断 无情最逍遥
- angular---代码详解(第三篇)
- How to develop OpenGL ES (GLES) 2.0 applications on Linux
- Maven仓库——私服介绍
- CSU-1818 Crusher’s Code(期望dp)
- somwecqskckwaaw
- 前端面试题(中)
- 从dts里的of_device节点中获取变量值实例
- jquery 获取子iframe里面的元素
- 京东小三角做法
- MIPS寄存器使用约定
- linux文件管理
- 重温数据结构之四——队列与堆栈