码迷,mamicode.com
首页 > 其他好文 > 详细

Hdu 4336 Card Collector (状态概率DP|容斥原理)

时间:2015-02-03 09:36:21      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:状态压缩   概率dp   容斥原理   

详细的题目大意与解析大家参考一下kuangbin的文章。

kuangbin链接

这边说一下自己对于kuangbin代码以及容斥原理位元素枚举的理解与解释,希望对大家有所帮助。

状态DP AC代码:状态压缩的思想我就不赘述了,我也只是略懂,这边仅仅分析一下状态方程

由于量比较多,我这边有的便用文字代替,有利于描述。

dp[i]表示i状态达到满状态(即收集满n个物品,以下称满状态)所需要的期望。

那么i状态当中收集了x的物品,剩余n-x个物品没有收集

那么dp[i]=p*dp[i]+p2*dp[i2]+1;

这边解释一下上面的变量:

p表示的是假如下一次抽到的物品是已经搜集过的物品被抽到的概率之和,至于为什么要这样子,有概率DP基础的应该知道吧?状态分解,事件之和。

p2表示的是抽到没有收集过物品的概率,已经加上该物品之后的状态要达到满状态的期望,这边少了一个累加,所有没有收集的累加。依然依据的是状态的分解和事件之和。

假如有问题的话,欢迎评论指教。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
double dp[1 << 22];
double p[22];
int main()
{
	int n;
	while (cin >> n)
	{
		double op = 0;
		for (int i = 0; i <n; i++)
		{
			scanf("%lf", &p[i]);
			op += p[i];
		}
		op = 1 - op;
		dp[(1 << n) - 1] = 0;
		for (int i = (1 << n) - 2; i >= 0; i--)
		{
			double x = 0, sum = 1;
			for (int j = 0; j < n;j++)
			if (i&(1 << j)) x += p[j];
			else            sum += p[j] * dp[i|(1 << j)];
			dp[i] = sum / (1 - op - x);
		}
		printf("%.5lf\n", dp[0]);
	}
}


容斥原理应用:位运算枚举

这边可能你需要百度一下容斥原理是怎么一个东西,再回来看我的解释会比较清楚,因为容斥原理我也不知道怎么讲才清楚,这边提供一个别人推荐的文章。容斥原理

好了,现在你可能已经懂了什么是容斥原理。

那么这边我以n=3为例。并且按照状态压缩来讲解。

我现在是要得到111的

那么1/p1(p1表示的是事件1发生的概率)表示的是1发生的概率,这边包括001,011,111,101

同理,1/p2包括的是010,011,111,110

1/p3:100,101,111,110

将三个相加,所得到的便是状态001,010,100,011*2,101*2,110*2,111*3这些状态对应的期望.我们需要的是111状态,所以需要想办法减去其他的

1/(p2+p1)包括,011,010,001,111,110,101

1/(p2+p3)包括110,100,010,111,101,011

1/(p3+p1)包括101,001,100,111,011,110

1/(p1+p2+p3)包括001,010,100,110,011,101,111

根据容斥原理,减去上面三个,得到:(全是负的)001,010,100,110,011,101

所以最后再加上一个1/(p1+p2+p3)即得到111状态对应的期望。

1/p对应的是期望,希望大家好好理解,我也是看了很久,有问题的欢迎跟我交流哈。QQ:417033420

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

double p[22];
int main()
{
	int n;
	while (scanf("%d", &n) == 1)
	{
		for (int i = 0; i<n; i++)scanf("%lf", &p[i]);
		double ans = 0;
		for (int i = 1; i<(1 << n); i++)
		{
			int cnt = 0;
			double sum = 0;
			for (int j = 0; j<n; j++)
			if (i&(1 << j))
			{
				sum += p[j];
				cnt++;
			}
			if (cnt & 1)ans += 1.0 / sum;
			else ans -= 1.0 / sum;
		}
		printf("%.5lf\n", ans);
	}
	return 0;
}


Hdu 4336 Card Collector (状态概率DP|容斥原理)

标签:状态压缩   概率dp   容斥原理   

原文地址:http://blog.csdn.net/u013611908/article/details/43418085

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!