题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率为 p1,p2,⋯pn
(2)状压DP解决:
。每包至多一张卡片,可能没有卡片。求需要买多少包才能拿到所有的N张卡片,求次数的期望。
思路:(1)先用容斥原理解决:n<=20,二进制表示取不取的状态,1取0不取,故共有1<<n种状态。然后枚举每种状态,然后枚举每个卡片是否可以取……
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define MM 500002
#define MN 1002
#define INF 168430090
using namespace std;
typedef long long ll;
int main()
{
int n;
while(cin>>n)
{
int i,j,t;
double ans,sum=0,p[21];
for(i=0;i<n;i++)
cin>>p[i];
for(i=1;i<(1<<n);i++) //枚举每种状态,i化为二进制就知道其中原理了
{
ans=0; t=0;
for(j=0;j<n;j++)
if(i&(1<<j)) {ans+=p[j];t++;} //j枚举每种卡片是否同i中对应的位置也是1,是则取
if(t&1) sum+=1/ans; //容斥原理中奇加偶减
else sum-=1/ans;
}
printf("%.4lf\n",sum);
}
return 0;
}
(2)状压DP解决:
以下是队友的思路:第一次做状压DP,看的是队友怎么分析的,然后现在终于理解了。
于是包中没有卡片的概率就是
pno=1−∑i=1npi
用20个二进制位来表示现在拿到了哪些卡片。卡片全拿到(全为1)的状态显然是只需要拿0次。接下来我们枚举状态(每次减1),对于每种状态考虑此时买一包的情况。
我们有
Ex=∑nothavepiEi+(∑havepi+pno)Ex+1
整理得
Ex=∑nothavepiEi+11−∑havepi−pno
如果买的是之前有的,那么状态不改变,同时将概率加到px里。如果买的是之前没有的,那就把那种情况发生的概率乘以那时状态的期望(一定是计算过的,因为比此时状态大的状态必然之前算过)加到sum里。最后dp[i]=期望次数+1/(1-px-没有卡片的概率)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define MM 500002
#define MN 1002
#define INF 168430090
using namespace std;
typedef long long ll;
double dp[1<<21],p[21];
int main()
{
int n;
while(cin>>n)
{
int i,j;
double s=0;
for(i=0;i<n;i++)
cin>>p[i],s+=p[i];
s=1-s; dp[(1<<n)-1]=0;//全部为1的情况为0
for(i=(1<<n)-2;i>=0;i--) //从二进制中1最多的递推到1少的,下面用或真是精辟啊
{
double sum=0,px=0;
for(j=0;j<n;j++)
if((i|(1<<j))!=i) sum+=p[j]*dp[i|(1<<j)];
else px+=p[j];
dp[i]=(sum+1)/(1-px-s);
}
printf("%.4lf\n",dp[0]);
}
return 0;
}
本文探讨了在有限数量卡片的情况下,通过购买包获取所有卡片所需的期望次数问题。提出了两种解决方案:一是使用容斥原理进行枚举计算;二是采用状态压缩动态规划方法,通过状态转移方程高效求解。

2968

被折叠的 条评论
为什么被折叠?



