SDUT-2878-Circle(概率DP/高斯消元)

Circle

Time Limit: 2000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

You have been given a circle from 0 to n - 1. If you are currently at x, you will move to (x - 1) mod n or (x + 1) mod n with equal probability. Now we want to know the expected number of steps you need to reach x from 0.

输入

The first line contains one integer T — the number of test cases.
 
Each of the next T lines contains two integers n, x (0  ≤ x < n ≤ 1000) as we mention above.

输出

For each test case. Print a single float number — the expected number of steps you need to reach x from 0. The figure is accurate to 4 decimal places.

示例输入

3
3 2
5 4
10 5

示例输出

2.0000
4.0000
25.0000

提示

 

来源

2014年山东省第五届ACM大学生程序设计竞赛

示例程序


 E[p]=0.5*E[p-1]+0.5*E[p+1]+1

 即  -0.5*E[p-1]+E[p]-0.5*E[p+1]=1。

可以用高斯消元来做,

另外根据规律可以得到d[i]=(n-1)+(n-3)+(n-5)。。。


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <queue>
using namespace std;
#define eps 1e-9
const int MAXN = 1005;
int p,n,m;
double a[MAXN][MAXN],x[MAXN];
bool free_x[MAXN];//标记是否是不确定的变元
//int equ,var;
int sign(double x)
{
    return (x>eps)-(x<-eps);
}
/**返回值:
-1 无解
0 有且仅有一个解
>=1 有多个解,根据free_x判断哪些是不确定的解
*/
int Gauss()
{
    int i,j;
    int row,col,max_r;
    m=n;///n个方程,n个变量的那种情况
    for(row=0,col=0; row<m&&col<n; row++,col++)
    {
        max_r=row;
        for(i=row+1; i<m; i++) ///找到当前列所有行中的最大值(做除法时减小误差)
        {
            if(sign(fabs(a[i][col])-fabs(a[max_r][col]))>0)
                max_r=i;
        }
        if(max_r!=row)
        {
            for(j=row; j<n+1; j++)
                swap(a[max_r][j],a[row][j]);
        }
        if(sign(a[row][col])==0)///当前列row行以下全为0(包括row行)
        {
            row--;
            continue;
        }
        for(i=row+1; i<m; i++)
        {
            if(sign(a[i][col])==0)
                continue;
            double tmp=a[i][col]/a[row][col];
            for(j=col; j<n+1; j++)
                a[i][j]-=a[row][j]*tmp;
        }
    }
    for(i=row; i<m; i++) ///col=n存在0...0,a的情况,无解
    {
        if(sign(a[i][col]))
            return -1;
    }
    if(row<n)///存在0...0,0的情况,有多个解,自由变元个数为n-row个
    {
        for(i=row-1; i>=0; i--)
        {
            int free_num=0;///自由变元的个数
            int free_index;///自由变元的序号
            for(j=0; j<n; j++)
            {
                if(sign(a[i][j])!=0&&free_x[j])
                    free_num++,free_index=j;
            }
            if(free_num>1)
                continue;///该行中的不确定的变元的个数超过1个,无法求解,它们仍然为不确定的变元
            ///只有一个不确定的变元free_index,可以求解出该变元,且该变元是确定的
            double tmp=a[i][n];
            for(j=0; j<n; j++)
            {
                if(sign(a[i][j])!=0&&j!=free_index)
                    tmp-=a[i][j]*x[j];
            }
            x[free_index]=tmp/a[i][free_index];
            free_x[free_index]=false;
        }
        return n-row;
    }
    ///有且仅有一个解,严格的上三角矩阵(n==m)
    for(i=n-1; i>=0; i--)
    {
        double tmp=a[i][n];
        for(j=i+1; j<n; j++)
            if(sign(a[i][j])!=0)
                tmp-=a[i][j]*x[j];
        x[i]=tmp/a[i][i];
    }
    return 0;
}///模板结束
// -0.5*E[p-1]+E[p]-0.5*E[p+1]=1
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&p);
        memset(a,0,sizeof(a));
        //memset(x,1,sizeof(x));
        //x[p]=0;
        for(int i=0; i<n; ++i)
        {
            a[i][i]=1;
            a[i][n]=1;
            if(i==p)
            {
                a[i][n]=0;
                continue;
            }
            if(i==0)
            {
                a[i][n-1]=-0.5;
                a[i][i+1]=-0.5;
                continue;
            }
            if(i==n-1)
            {
                a[i][i-1]=-0.5;
                a[i][0]=-0.5;
                continue;
            }
            a[i][i-1]=-0.5;
            a[i][i+1]=-0.5;
        }
       // equ=var=n;
        Gauss();
        //cout<<x[0]<<endl;
        printf("%0.4lf\n",x[0]);
    }
    return 0;
}
//////////////////////////////////////////////////////////////////////////
double d[1010];
int main()
{
    int t,x;
    scanf("%d",&t);
    while(t--)
    {
        d[0]=0;
        scanf("%d%d",&n,&x);
        if(x>n/2)
            x=n-x;
        for(int i=1;i<=n/2;++i)
            d[i]=d[i-1]+(n-(2*i-1));
        printf("%.4lf\n",d[x]);
    }
    return 0;
}


SDUT-2878-Circle(概率DP/高斯消元)

你可能感兴趣的:(C++,ACM)