求期望

高斯消元 求期望
存个代码


hdu 4418
题解来源http://972169909-qq-com.iteye.com/blog/1689107


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
const double eps=1e-10;
const int maxn=255;
int n,m,tot,poi,X,Y;
int cod[maxn];
double a[maxn][maxn],x[maxn],p[maxn];
double sum;

char mar[20][20];
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int gauss_cpivot(int n,int m,double a[][maxn],double b[]){
int i,j,k,row;
double maxp,t;
for (k=0;k<m;k++){
for (maxp=0,i=k;i<n;i++)
if (fabs(a[i][k])>fabs(maxp))
maxp=a[row=i][k];
if (fabs(maxp)<eps)
return 0;
if (row!=k){
for (j=k;j<m;j++)
t=a[k][j],a[k][j]=a[row][j],a[row][j]=t;
t=b[k],b[k]=b[row],b[row]=t;
}
for (j=k+1;j<m;j++){
a[k][j]/=maxp;
for (i=k+1;i<n;i++)
a[i][j]-=a[i][k]*a[k][j];
}
b[k]/=maxp;
for (i=k+1;i<n;i++)
b[i]-=b[k]*a[i][k];
}
for (i=n-1;i>=0;i--)
for (j=i+1;j<m;j++)
b[i]-=a[i][j]*b[j];
return 1;
}
bool bfs()
{
  queue<int>q;
  q.push(X);
  memset(cod,-1,sizeof(cod));
  memset(a,0,sizeof(a));
  cod[X]=0;
  tot=1;

  bool flag;
  int i;
  int now;
  flag=false;
  while (!q.empty())
  {
    now=q.front(); q.pop();
   // printf("poi=%d nowx=%d nowy=%d\n",poi,now.x,now.y);
    a[cod[now]][cod[now]]=1;
    x[cod[now]]=sum;
    if (now==Y || now==n-Y)
    {
      flag=true;
      x[cod[now]]=0;
    }
    else
    {
      for (i=1;i<=m;i++)
      {
        if (fabs(p[i])<eps) continue;
        int nex=(now+i)%n;
        if (cod[nex]==-1)
        {
          cod[nex]=tot++;
          q.push(nex);
        }
        a[cod[now]][cod[nex]]-=p[i];
      }
    }

  }
  return flag;

}
int main()
{
int cases,D,i;
  while (~scanf("%d",&cases))
    {
      while (cases--)
      {
        scanf("%d%d%d%d%d",&n,&m,&Y,&X,&D);
          n=2+2*(n-2); sum=0.0;
          for (i=1;i<=m;i++)
          {
            scanf("%lf",&p[i]);
            p[i]*=0.01;
            sum+=i*p[i];
          }
            if (X==Y) printf("0.00\n");
             else
             {
              if (D) X=(n-X)%n;
              if (!bfs()) printf("Impossible !\n");
             else
             {
              gauss_cpivot(tot,tot,a,x);
             // for (int i=0;i<tot;i++) printf(" %.3f",x[i]);
             // printf("\n");
              printf("%.2f\n",x[cod[X]]);
             }
             }
           }

    }
    return 0;
}

hdu 2262
题解来源:http://blog.csdn.net/gatevin/article/details/42127647


因为没有清空a数组wa了n发
感觉好像对期望的套路有点理解了


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
const double eps=1e-10;
const int maxn=255;
int n,m,tot,poi;
int cod[20][20];
double a[maxn][maxn],x[maxn];
struct pt
{
  int x,y;

}st;
char mar[20][20];
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int gauss_cpivot(int n,int m,double a[][maxn],double b[]){
int i,j,k,row;
double maxp,t;
for (k=0;k<m;k++){
for (maxp=0,i=k;i<n;i++)
if (fabs(a[i][k])>fabs(maxp))
maxp=a[row=i][k];
if (fabs(maxp)<eps)
return 0;
if (row!=k){
for (j=k;j<m;j++)
t=a[k][j],a[k][j]=a[row][j],a[row][j]=t;
t=b[k],b[k]=b[row],b[row]=t;
}
for (j=k+1;j<m;j++){
a[k][j]/=maxp;
for (i=k+1;i<n;i++)
a[i][j]-=a[i][k]*a[k][j];
}
b[k]/=maxp;
for (i=k+1;i<n;i++)
b[i]-=b[k]*a[i][k];
}
for (i=n-1;i>=0;i--)
for (j=i+1;j<m;j++)
b[i]-=a[i][j]*b[j];
return 1;
}
bool bfs()
{
  queue<pt>q;
  q.push(st);
  memset(cod,-1,sizeof(cod));
  memset(a,0,sizeof(a));
  cod[st.x][st.y]=0;
  tot=1;
  poi=0;

  bool flag;
  int i;
  pt now;
  flag=false;
  while (!q.empty())
  {
    now=q.front(); q.pop();
   // printf("poi=%d nowx=%d nowy=%d\n",poi,now.x,now.y);
    a[poi][cod[now.x][now.y]]=1;
    x[poi]=1;
    if (mar[now.x][now.y]=='$')
    {
      flag=true;
      x[poi]=0;
    }
    else
    {
     int  fx=4;
      for (i=0;i<4;i++)
      {
        int nx=now.x+dx[i];
        int ny=now.y+dy[i];
        if (nx<0 || nx>=n || ny<0 || ny>=m ||mar[nx][ny]=='#') fx--;
      }
      for (i=0;i<4;i++)
      {
        int nx=now.x+dx[i];
        int ny=now.y+dy[i];
        if (!(nx<0 || nx>=n || ny<0 || ny>=m ||mar[nx][ny]=='#'))
        {
          if (cod[nx][ny]==-1)
          {
            cod[nx][ny]=tot++;
            pt nn;
            nn.x=nx; nn.y=ny;
          //  printf("nx=%d ny=%d\n",nx,ny);
            q.push(nn);
          }
          a[poi][cod[nx][ny]]=-1.0/fx;
        }

      }
    }
    poi++;
  }
  return flag;

}
int main()
{

  while (~scanf("%d%d",&n,&m))
    {
       for (int i=0;i<n;i++)
       {
        scanf("%s",mar[i]);
        for (int j=0;j<m;j++)
          if (mar[i][j]=='@') {st.x=i; st.y=j;}
       }
       if (!bfs()) printf("-1\n");
       else
       {
        gauss_cpivot(poi,tot,a,x);
       // for (int i=0;i<tot;i++) printf(" %.3f",x[i]);
       // printf("\n");
        printf("%.6f\n",x[cod[st.x][st.y]]);
       }

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值