TopCoder[SRM513 div 1]:(500)
Posted G . H . O . S . T . R . E . A
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TopCoder[SRM513 div 1]:(500)相关的知识,希望对你有一定的参考价值。
|
题意:你有n*m张卡片,总共n*m/2种,每种有两张。每次操作时你可以翻开两张,若一样,则它们不再翻回去;否则,这两张卡面会向你展示后再翻回去(不改变位置),假设你记忆力很好,能够记住牌的种类。求出至少进行多少次操作,可以使所有牌都同时正面朝上。注意,一次操作翻牌是有先后的,即你可以先翻一张牌,看过其种类后,再决定翻第二张牌。
题解:
假设翻到一样的牌,它们就会被消掉。dp[i][j]表示场上还有i+j张牌未被消掉,已经翻开过其中i张牌(即知道其种类),剩下的j张牌还未被翻开过。
每次操作一定会先翻一张未被翻过的牌,若其与i张牌中的一张对应,则第二张牌一定翻这张,把它们消掉。若是一张新的牌,则第二张牌一定也翻未被翻过的牌。
计算每种情况出现的概率与期望,以j为阶段、i为状态,进行动态规划。
代码:
1 double dp[2502][2502]; 2 class PerfectMemory 3 { 4 public: 5 double getExpectation(int N, int M) 6 { 7 //$CARETPOSITION$ 8 int n=N*M; dp[0][0]=0; 9 for(int j=0;j<=n;j++) 10 for(int i=0;i<=n;i++) 11 { 12 if((i==0)and(j==0))continue; dp[i][j]=10000000; 13 if(i>j)continue; if(i+j>n)continue; if((j-i)%2==1)continue; 14 dp[i][j]=0; double p,p2,a1; 15 p=i; p=p/j; p2=1-p; 16 if((j>0)and(i>0)) 17 { 18 dp[i][j]=dp[i][j]+p*(1+dp[i-1][j-1]); 19 } 20 double b,c,d; 21 if(j>1) 22 { 23 b=1; b=b/(j-1); c=j-2-i; c=c/(j-1); d=1-b-c; 24 a1=b*(1+dp[i][j-2])+c*(1+dp[i+2][j-2])+d*(2+dp[i][j-2]); 25 dp[i][j]=dp[i][j]+p2*a1; 26 } 27 } 28 return dp[0][n]; 29 30 } 31 };
以上是关于TopCoder[SRM513 div 1]:(500)的主要内容,如果未能解决你的问题,请参考以下文章