POJ 2096

题意:
输入n,s表示这里存在n种漏洞和s个系统(0<n,s<=1000)。工程师可以花费一天去找出一个漏洞——这个漏洞可以是以前出现过的种类,也可能是未曾出现过的种类,同时,这个漏洞出现在每个系统的概率相同。要求得出找到n种漏洞,并且在每个系统中均发现漏洞的期望天数。
个人感觉此题的方程状态还是比较好想的,不过化简式子有点烦。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
const int N=1e3+5;
int n,m;
double inf,f[N][N];
/*
对于期望dp我常常会想,如果就是取不到某一个值,那不就是永远无解了吗?
事实上,怎么可能这样计算呢?
这不是无解,而是我们的方法不可行罢了。 
dp[i][j]记录j个系统中发现i个bug后距成功的期望天数
这个方案是可行的,只要输出时输出dp[0][0]即可,在这里,dp[n][s]为0,然后自大而小转移到dp[0][0]即可。
有了状态,就需要转移方程了
能转移到dp[i][j]的共有四种情况:
1.新bug,新系统:值:(dp[i+1][j+1]+1),概率:(n-i)(s-j)/ns
2.新bug,旧系统:值:(dp[i+1][j]+1),概率:(n-i)j/ns
3.旧bug,新系统:值:(dp[i][j+1]+1),概率:i(s-j)/ns
4.旧bug,旧系统:值:(dp[i][j]+1),概率:ij/ns
也就是说:
dp[i][j]=(dp[i+1][j+1]+1)*(n-i)(s-j)/ns+(dp[i+1][j]+1)*i(s-j)/ns+(dp[i][j+1]+1)*(n-i)j/ns+(dp[i][j]+1)*ij/ns,
这时,我们发现等式两侧都有dp[i][j],我们需要把它整理出来
原式<=>ns*dp[i][j]=(dp[i+1][j+1]+1)*(n-i)(s-j)+(dp[i+1][j]+1)*i(s-j)+(dp[i][j+1]+1)*(n-i)j+(dp[i][j]+1)*ij
  <=>(ns-ij)*dp[i][j]=(dp[i+1][j+1]+1)*(n-i)(s-j)+(dp[i+1][j]+1)*i(s-j)+(dp[i][j+1]+1)*(n-i)j+ij
  <=>(ns-ij)*dp[i][j]=dp[i+1][j+1]*(n-i)(s-j)+ns-is-nj+ij+dp[i+1][j]*i(s-j)+is-ij+dp[i][j+1]*(n-i)j+nj-ij+ij
  <=>(ns-ij)*dp[i][j]=dp[i+1][j+1]*(n-i)(s-j)+dp[i+1][j]*i(s-j)+dp[i][j+1]*(n-i)j+ns
  <=>dp[i][j]=(dp[i+1][j+1]*(n-i)(s-j)+dp[i+1][j]*i(s-j)+dp[i][j+1]*(n-i)j+ns)/(ns-ij)
*/ 
double dfs(int i,int j)
{
	if (f[i][j]!=inf) return f[i][j];
	if (i==n && j==m) return 0;
	double ans=0;
	ans=(n*m+dfs(i+1,j+1)*(n-i)*(m-j)+dfs(i,j+1)*i*(m-j)+dfs(i+1,j)*(n-i)*j)/(n*m-i*j);
	f[i][j]=ans;
	return f[i][j];
}

int main(){
	while (~scanf("%d%d",&n,&m))
	{
		inf=-2e9;
		for (register int i=0; i<=n; ++i)
		for (register int j=0; j<=m; ++j) f[i][j]=inf;
		printf("%.4f\n",dfs(0,0));
	}	
return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值