http://acm.timus.ru/problem.aspx?space=1&num=1776
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2507
dp 关键用概率呀 只有理解好其中的概率原理才可以呀
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<queue> #include<algorithm> #define LL long long using namespace std; const int N=405; double ans[N][N];//有i个烟花的情况下 需要j个10秒的概率 double sum[N][N];//有i个烟花的情况下 需要时间小于等于j个10秒的概率 int main() { for(int i=0;i<N;++i) for(int j=0;j<N;++j) {ans[i][j]=0.0;sum[i][j]=0.0;} for(int i=0;i<N;++i) sum[0][i]=1.0; ans[1][0]=1.0; for(int i=0;i<N;++i) sum[1][i]=1.0; for(int i=2;i<N;++i) { for(int j=1;j<i;++j) { for(int l=0,r=i-1;l<i;++l,--r) { ans[i][j]+=(ans[l][j-1]*sum[r][j-1]+sum[l][j-1]*ans[r][j-1]-ans[l][j-1]*ans[r][j-1]); } ans[i][j]/=i;//i个选择 所以要除以i } for(int j=1;j<N;++j) sum[i][j]=sum[i][j-1]+ans[i][j]; } int T; cin>>T; int n; while(T--) { cin>>n; n=n-2;//先点燃两边的 最后结果再把时间加上 double tmp=0.0; for(int i=0;i<n;++i) tmp+=(ans[n][i]*i);//概率乘上时间段个数 printf("%.4f\n",(tmp+1)*10.0); } return 0; }