2011年北京区域赛I-Activation
2012-10-03 19:35
169 查看
开始做的时候无从下手,这题就是一个概率dp。很多的细节。dp[i][j]指的是在有j个人的时候Tomato排的位置为j这个状态时的概率。这个题需要考虑的就是循环的问题,第一是p1的循环,所以对p2,p3,p4的概率进行了修改使他们的和为1.然后就是每次第一个人都失败,所以对于dp[m]
的概率是每轮的概率和相加。还有一点就是dp[i][j]=dp[i+1][j+1]*p3+dp[i+1][j]*p2;因为是一个循环所以要对这个式子进行化简。先将最开始的值求出来。我先贴一个T掉的版本,这个版本更容易理解思路。
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double dp[2010][2010];
double p(double a,int n){
if(n==0)
return 1.0;
else{
double cnt=p(a,n/2);
if(n%2)
return cnt*cnt*a;
else
return cnt*cnt;
}
}
main(){
double p1,p2,p3,p4;
int n,m,k;
while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){
p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);
memset(dp,0,sizeof(dp));
dp[m]
=1/(1-p(p2,n));
for(int i=1;i<m;i++){
dp[i]
=dp[m]
*p(p2,m-i);
}
for(int i=m+1;i<=n;i++){
dp[i]
=dp[m]
*p(p2,n+m-i);
}
double ans=0;
for(int j=n-1;j>=1;j--){
double tmp=1-p(p2,j);
for(int i=j;i>=1;i--){
if(i==j){
int c=i-1;
for(int kk=0;kk<j;kk++){
dp[i][j]+=dp[c%j+2][j+1]*p3*p(p2,kk);
c++;
}
dp[i][j]=dp[i][j]/tmp;
}
else{
if(!(i==1 && j==1)){
dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;
}
else{
dp[1][1]=(dp[2][2]*p3)/(1-p2);
}
}
if(i<=k)
ans+=dp[i][j];
//printf("%lf ",dp[i][j]);
}
// printf("\n");
}
for(int i=1;i<=k;i++){
ans+=dp[i]
;
}
printf("%.5lf\n",ans*p4);
}
}
后来通过变形,把这个式子改好了。
但是这道题还有一个坑就是p4==0的时候需要特判,因为这样我为此还WA了一次。
AC代码:
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double dp[2010][2010];
double const eps=1e-5;
double p(double a,int n){
if(n==0)
return 1.0;
else{
double cnt=p(a,n/2);
if(n%2)
return cnt*cnt*a;
else
return cnt*cnt;
}
}
main(){
double p1,p2,p3,p4;
int n,m,k;
while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){
if(p4<eps){
printf("0.00000\n");
continue;
}
p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);
memset(dp,0,sizeof(dp));
dp[m]
=1/(1-p(p2,n));
for(int i=1;i<m;i++){
dp[i]
=dp[m]
*p(p2,m-i);
}
for(int i=m+1;i<=n;i++){
dp[i]
=dp[m]
*p(p2,n+m-i);
}
double ans=0;double cnt=0;
int c=n-2;
for(int kk=0;kk<n-1;kk++){
cnt+=dp[c%(n-1)+2]
*p3*p(p2,kk);
c++;
}
for(int j=n-1;j>=1;j--){
double tmp=1-p(p2,j);
for(int i=j;i>=1;i--){
if(i==j){
dp[i][j]=cnt/tmp;
cnt=0;
cnt+=dp[i][j]*p3;
}
else{
if(!(i==1 && j==1)){
dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;
}
else{
dp[1][1]=(dp[2][2]*p3)/(1-p2);
}
}
if(i<=k)
ans+=dp[i][j];
if(i!=1 && i!=j)
cnt+=dp[i][j]*p3*p(p2,i-1);
//printf("%lf ",dp[i][j]);
}
//printf("\n");
}
for(int i=1;i<=k;i++){
ans+=dp[i]
;
}
printf("%.5lf\n",ans*p4);
}
}
的概率是每轮的概率和相加。还有一点就是dp[i][j]=dp[i+1][j+1]*p3+dp[i+1][j]*p2;因为是一个循环所以要对这个式子进行化简。先将最开始的值求出来。我先贴一个T掉的版本,这个版本更容易理解思路。
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double dp[2010][2010];
double p(double a,int n){
if(n==0)
return 1.0;
else{
double cnt=p(a,n/2);
if(n%2)
return cnt*cnt*a;
else
return cnt*cnt;
}
}
main(){
double p1,p2,p3,p4;
int n,m,k;
while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){
p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);
memset(dp,0,sizeof(dp));
dp[m]
=1/(1-p(p2,n));
for(int i=1;i<m;i++){
dp[i]
=dp[m]
*p(p2,m-i);
}
for(int i=m+1;i<=n;i++){
dp[i]
=dp[m]
*p(p2,n+m-i);
}
double ans=0;
for(int j=n-1;j>=1;j--){
double tmp=1-p(p2,j);
for(int i=j;i>=1;i--){
if(i==j){
int c=i-1;
for(int kk=0;kk<j;kk++){
dp[i][j]+=dp[c%j+2][j+1]*p3*p(p2,kk);
c++;
}
dp[i][j]=dp[i][j]/tmp;
}
else{
if(!(i==1 && j==1)){
dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;
}
else{
dp[1][1]=(dp[2][2]*p3)/(1-p2);
}
}
if(i<=k)
ans+=dp[i][j];
//printf("%lf ",dp[i][j]);
}
// printf("\n");
}
for(int i=1;i<=k;i++){
ans+=dp[i]
;
}
printf("%.5lf\n",ans*p4);
}
}
后来通过变形,把这个式子改好了。
但是这道题还有一个坑就是p4==0的时候需要特判,因为这样我为此还WA了一次。
AC代码:
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double dp[2010][2010];
double const eps=1e-5;
double p(double a,int n){
if(n==0)
return 1.0;
else{
double cnt=p(a,n/2);
if(n%2)
return cnt*cnt*a;
else
return cnt*cnt;
}
}
main(){
double p1,p2,p3,p4;
int n,m,k;
while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=-1){
if(p4<eps){
printf("0.00000\n");
continue;
}
p2=p2/(1-p1);p3=p3/(1-p1);p4=p4/(1-p1);
memset(dp,0,sizeof(dp));
dp[m]
=1/(1-p(p2,n));
for(int i=1;i<m;i++){
dp[i]
=dp[m]
*p(p2,m-i);
}
for(int i=m+1;i<=n;i++){
dp[i]
=dp[m]
*p(p2,n+m-i);
}
double ans=0;double cnt=0;
int c=n-2;
for(int kk=0;kk<n-1;kk++){
cnt+=dp[c%(n-1)+2]
*p3*p(p2,kk);
c++;
}
for(int j=n-1;j>=1;j--){
double tmp=1-p(p2,j);
for(int i=j;i>=1;i--){
if(i==j){
dp[i][j]=cnt/tmp;
cnt=0;
cnt+=dp[i][j]*p3;
}
else{
if(!(i==1 && j==1)){
dp[i][j]=(p2*(dp[i+1][j]*tmp-dp[i+1][j+1]*p3*(1-tmp)/p2)+dp[i+1][j+1]*p3)/tmp;
}
else{
dp[1][1]=(dp[2][2]*p3)/(1-p2);
}
}
if(i<=k)
ans+=dp[i][j];
if(i!=1 && i!=j)
cnt+=dp[i][j]*p3*p(p2,i-1);
//printf("%lf ",dp[i][j]);
}
//printf("\n");
}
for(int i=1;i<=k;i++){
ans+=dp[i]
;
}
printf("%.5lf\n",ans*p4);
}
}
相关文章推荐
- HDU 4089 Activation 概率DP 2011年区域赛北京现场赛I题
- 2011年 北京区域赛A题 Qin Shi Huang's National Road System // hdu 4081 Qin Shi Huang's National Road System 最优比率生成树
- 2011年北京区域赛A题
- 2008 北京区域赛 Priest John's Busiest Day
- hdu5122 K.Bro Sorting (2014ACM亚洲区域赛北京赛区重现)
- 2011年北京对联批发
- HDU 5124 hihocoder 1249 Xiongnu's Land (2015北京区域赛A)
- 中国 WebLogic User Group 2011年北京第二次线下活动
- 北京分区域分时段限行政策年底前即将出台
- 2011年 ACM/ICPC 北京赛区 A题 Qin shi huang's national road system
- 2014 北京区域赛 F Fluorescent HDU5117 (数学+状压+dp)
- 摩拜将限制北京用户停车区域 违停收取管理费
- 2016亚洲区域赛现场赛北京赛区e题
- 2011 北京赛区 I bupt 246 Activation
- 08年acm区域赛北京赛区 部分题解题报告
- 2015 北京区域赛现场赛 部分题解
- 2011 北京区域赛 Hou Yi's secret // hdu 4082
- 2015北京区域赛 A.Xiongnu's Land(二分或者标记法)
- 2017ACM-ICPC北京区域现场赛 G题 hihocoder1633
- 2016亚洲区域赛现场赛北京赛区k题