概率DP問題整理(一)

2021-06-17 22:21:52 字數 4318 閱讀 1986

第一題:hdu 3853 

簡單概率dp題。注意思維逆過來考慮。

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 1005

struct probab

probab[maxn][maxn];

double dp[maxn][maxn];

int main()

}memset(dp,0,sizeof(dp));

for(int i=r;i>=1;i--)

}printf("%.3lf\n",dp[1][1]);

}return 0;

}

第二題:hdu 4336

狀態壓縮+概率dp。

狀態轉移方程:

dp[s] = ps*dp[s]+sigma(  p[i]*dp[ s ^ (1<

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 21

double probab[maxn];

double dp[1《第三題:poj 3744 scout yyf i

思路摘自其他人:

題意:在一條不滿地雷的路上,你現在的起點在1處。在n個點處布有地雷,1<=n<=10。地雷點的座標範圍:[1,100000000].

每次前進p的概率前進一步,1-p的概率前進1-p步。問順利通過這條路的概率。就是不要走到有地雷的地方。

設dp[i]表示到達i點的概率,則 初始值 dp[1]=1.

很容易想到轉移方程: dp[i]=p*dp[i-1]+(1-p)*dp[i-2];

但是由於座標的範圍很大,直接這樣求是不行的,而且當中的某些點還存在地雷。

n個有地雷的點的座標為 x[1],x[2],x[3]```````x[n].

我們把道路分成n段:

1~x[1];

x[1]+1~x[2];

x[2]+1~x[3];``

`x[n-1]+1~x[n].

這樣每一段只有乙個地雷。我們只要求得通過每一段的概率。乘法原理相乘就是答案。

對於每一段,通過該段的概率等於1-踩到該段終點的地雷的概率。

就比如第一段 1~x[1].  通過該段其實就相當於是到達x[1]+1點。那麼p[x[1]+1]=1-p[x[1]].

但是這個前提是p[1]=1,即起點的概率等於1.對於後面的段我們也是一樣的假設,這樣就乘起來就是答案了。

對於每一段的概率的求法可以通過矩陣乘法快速求出來。

另外注意:關於double,scanf要用%lf,printf只能用%f才對。

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 12

#define matrix_size 2

int place[maxn];

struct matrix

void setsize(int _size)

matrix operator = (const matrix & other)

*this = e;

}};matrix m;

void init(double p)

int main()

sort(place+1,place+1+n);

double ans = 1;

for(int i=1;i<=n;i++)

printf("%.7f\n",ans );

}return 0;

}

第四題:uva 11722 joining with friend

題目連線:

連續概率dp:

#include #include #include #include #include #include #include #include using namespace std;

const double eps = 1e-8;

struct point

point(int _x,int _y):x(_x),y(_y) {}

friend point operator + (point a,point b)

friend point operator - (point a,point b)

}; int dcmp(double x) //三態函式

double det(point a,point b) // 叉積,過載叉積函式

double det(point a,point b,point o) // 叉積

double det(point a,point b,point c,point d) // 叉積

//a,b,c,d是矩形的四個點

point a,b,c,d;

//p1,p2是y=x-w線段上的任意兩個點

//p3,p4是y=x+w線段上的任意兩個點

point p1,p2,p3,p4;

int t1, t2, s1, s2, w;

double init()

else if(bp<0 && ap<=0 && cp<=0 && dp>=0)

else if(bp<0 && cp<0 && ap>0 && dp>0)

else if(bp<0 && ap<0 && cp>0 && dp>0)

else

//處理上方的線段

bp = dcmp(det(p3,p4,b));

ap = dcmp(det(p3,p4,a));

cp = dcmp(det(p3,p4,c));

dp = dcmp(det(p3,p4,d));

double area2 = 0;

if(bp>=0) area2 = 0;

else if(bp<0 && ap>=0 && cp>=0)

else if(bp<0 && ap<=0 && cp<=0 && dp>=0)

else if(bp<0 && cp<0 && ap>0 && dp>0)

else if(bp<0 && ap<0 && cp>0 && dp>0)

else

return (area2 - area1)/(t2-t1)/(s2-s1);

}int main()

return 0;

}

第五題:uva 11762 - race to 1

題目連線:

質數分解轉換。

設:sum[x]表示1到x中有多少個素數,p[x]表示x的素數因子個數,不難發現遞推關係如下:

dp(x) = 1 + dp(x) * (sum[x] - p[x])/sum[x] + sigma(dp(x/yi)) /sum[x];其中yi是x的素因子。

兩邊同時乘sum[x].我們得到:

p[x] * dp(x) = sum[x] + sigma(dp(x/yi))

dp(x)即可求出。

注意用篩法求質數同時預處理出sum[x] 和p[x].

求篩法的時候要注意範圍和係數。

#include #include #include #include #include #include #include #include using namespace std;

#define maxn 1000002

int n;

int notprime[maxn+5];

vector primefactor[maxn+5];

int primesum[maxn+5];

double dp[maxn+5];

void init()

primefactor[i].push_back(i);}}

memset(primesum,0,sizeof(primesum));

for(int i=2;i<=maxn;i++)

memset(dp,0,sizeof(dp));

}double solve(int n)

{ if(n == 1) return 0;

if(dp[n]!=0) return dp[n];

double ans = 0;

for(int i=2;i<=n;i++)

{ans = 0;

for(int j=0;j

概率DP初步

題目簡述 乙個r行c列的格仔,起始點在 1,1 終點在 r,c 每一步可能的走法有 不動 向右走 向下走,每走一步花費兩點魔法值,現給出在每一點三種走法的概率,求走完迷宮時所花魔法值的期望。分析 運用dp演算法的話,首先需要確定乙個合適狀態來描述子問題的情況,很明顯本題的狀態可以定義為dp i j ...

概率dp入門

概率dp主要用於求解期望 概率等題目。轉移方程有時候比較靈活。一般求概率是正推,求期望是逆推。通過題目可以體會到這點。poj2096 collecting bugs include include include include include typedef long long ll using ...

骰子 概率dp

因為會有人被彈出佇列,所以我設定的期望dp為 於是有當只剩乙個人的時候,那個人必勝,再往下,先看它在隊首的情況,其他的情況呢,也就是不在隊首的時候呢,於是,連立這兩個方程組,可以得到 所以,就可以利用乙個pow來處理double型來解決這個問題了。include include include in...