首先分享一篇将这道题目讲的很好的博客:http://blog.youkuaiyun.com/kyleyoung_ymj/article/details/52097240
本来卡住了,看了这个博客就会做了。
然后说一下我做这道题目的感触:
1. 这个状态转移方程实际上我已经推导出来,但是因为之前没有做过概率的dp,误认为求期望要把所有可能情况的dp都算一下最后求平均,然后脑子里一算发现复杂度爆了,就没想下去。实际上,这种题目把dp的值直接设成最后的期望值,会有意想不到的效果。
2.对于这道题,在给的w很大的情况下,肯定二分答案就可以了——这其实应该是我们一开始做题目就应该想到的。但是,这也意味着,当w很大的时候,答案和w比较小是一样的,用来降低复杂度很方便。
3.打表法,就是先算出dp,再读数据,在这道题也是很好的应用。
寒假第一题,2017寒假加油!
#include<bits/stdc++.h>
using namespace std;
double dp[2010][30];
int k,w;
int main(void)
{
for(int j=1;j<=30;j++)
dp[0][j]=0;
for(int i=0;i<=2000;i++)
dp[i][0]=1000000000;
for(int i=1;i<=2000;i++)
{
dp[i][1]=(double)(i*(i+3))/(double)(2*(i+1));
for(int j=2;j<=30;j++)
{
double minn=100000000;
for(int k=1;k<=i;k++)
minn=min(minn,(k*dp[k-1][j-1]+(i-k+1)*dp[i-k][j])/(i+1));
dp[i][j]=minn+1;
}
}
while(cin>>k>>w)
{
if(w>25)
w=25;
printf("%.6f\n",dp[k][w]);
}
return 0;
}