1322Chocolate
我的代码老是runtime error 所以看了题解,有些地方还是看不懂啊
分析:
1》台上的巧克力数和当前拿出的巧克力的颜色有关系,设dp[i][j]表示拿出第i块的时候台上有j块巧克力的概率。巧克力i的颜色有两种情况:与桌上的巧克力颜色相同或者是与桌上的巧克力颜色不同
状态转移方程为:dp[i][j]=dp[i-1][j-1]*p1+dp[i-1][j+2]*p2;
p1=(c-j+1)/c, p2=(j+1)/c;
2》状态i仅和i-1有关,可以进行空间上的优化,用滚动数组实现
3》当拿出2*n+1奇数次巧克力,有k次出现同色,最后剩2*n+1-2*k=2*(n-k)+1,即桌子上剩余奇数个
当拿出2*n偶数次巧克力,有k次出现同色,最后剩2*n-2*k=2*(n-k),即桌上剩余偶数个
因此当(i+j)%2=1的时候,dp[i][j]=0.因为不可能出现拿奇数次桌上剩余偶数个和拿偶数次桌上剩余奇数个的情况
4》dp[0][0]=1.0
5》第一次提交直接超时了, 数据很多,当区域一个较大值后概率区域稳定了 .n>500 n=500+(n%2) 32MS n>300会wa掉
额。。。。我没有想到那条递归方程,说明我的实力还不够啊,另外呢,高手说到超时,我有点不明白啊
高手的代码
#include<stdio.h> #include<string.h> double dp[2][102]; int main() { int n, m, c, i, j; while(scanf("%d", &c)!=EOF) { if(c==0) break; scanf("%d%d", &n, &m); if(m>c||m>n||(m+n)%2==1) { printf("0.000\n"); continue; } memset(dp, 0, sizeof(dp)); dp[0][0]=1.0; int t=1; if(n>400) n=(n%2==0)?400:401; for(i=1; i<=n; i++) { for(j=0; j<=c&&j<=i; j++) { if((i+j)%2==1) {dp[t][j]=0; continue; } double p1=(c-j+1)*1.0/c, p2=(j+1)*1.0/c; dp[t][j]=0.0; if(j-1>=0) dp[t][j]+=dp[1-t][j-1]*p1; if(j+1<=i) dp[t][j]+=dp[1-t][j+1]*p2; } t=1-t; } printf("%.3lf\n", dp[n%2][m]); } return 0; }
我的代码,只能说是答案比较接近而已,当数据恶心时,应该是错的
#include "iostream" #include "iomanip" using namespace std; int total; int count(int c,int i){ int a=1,b=1,tem=0; for(int j=0;j<i;j++){ a*=(c-j);b*=(i-j); } tem+=a/b; return tem; } int main(){ int total,x,c,n,m,s,i; while(cin>>c&&c){ cin>>n>>m; total=0;x=0; if(n%2==0){ s=2; } else { s=1; } int top=1; for(i=s;i<=c;i+=s){ int ans; ans=count(c,i); if(i==m)x=ans; total+=ans; cout<<i<<' '<<ans<<endl; } cout<<"total "<<total<<endl;cout<<"x "<<x<<endl; if(m==0)x=1; double amount=x; if(x){ amount=(double)x/(total+1); } cout <<setprecision(3) <<amount <<endl; } }