第一題: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...