oj练习---dp专题

1.POJ 3744  Scout YYF I

经典的dp模型,但是要用到快速矩阵幂加速,分段的思想 

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

int mines[15];

void matrixMulti(double a[2][2], double b[2][2]){
    double i,j,k,l;
    i = a[0][0]*b[0][0]+a[0][1]*b[1][0];
    j = a[0][0]*b[0][1]+a[0][1]*b[1][1];
    k = a[1][0]*b[0][0]+a[1][1]*b[1][0];
    l = a[1][0]*b[0][1]+a[1][1]*b[1][1];
    a[0][0]=i,a[0][1]=j,a[1][0]=k,a[1][1]=l;
}

double quickPow(const double p, int x){
    if(x == -1){
        return 1.0;
    }
    double a[2][2] = {0, 1, 1-p, p}, res[2][2] = {1,0,0,1};
    while(x){
        //printf("this 3\n");
        if(x&1){
            matrixMulti(res, a);
        }
        x/=2;
        matrixMulti(a,a);
    }
    return res[0][1]*(1-p);
}

int main(){
    int num;
    double p, result;
    while(scanf("%d%lf",&num, &p) != EOF){
        memset(mines, 0, sizeof(mines));
        for(int i = 1 ; i <= num; ++i){
            scanf("%d", mines + i);
        }
        if(mines[1] == 1){
            printf("%.7f\n", 0.0);
            continue;
        }
        mines[0] = 0;
        result = 1.0;
        sort(mines, mines+num+1);
        for(int i = 1; i <= num; ++i){
            result *= quickPow(p, mines[i] - mines[i - 1] - 1);
        }
        if(result < 0){
            result = 0;
        }
        if(result > 1){
            result =1;
        }
        printf("%.7f\n", result);
    }
    return 0;
}

心得:1.dp[i]=dp[i-2]*(1-p)+dp[i-1]*p,其实就是连续跟1-p/p相乘,自然想到矩阵加速。2.快速幂的思想,将O(n)降成O(lg(n))。

3.[0, 1; 1-p, p]  * [dp[i-2]; dp[i-1]] =  [dp[i-1]; dp[i]],然后变成幂运算之后就可以加速了。多次乘以相同的数值其实就是幂运算(一个数就是整数幂,多个数的式子就是矩阵幂)

 

 

你可能感兴趣的:(算法,oj练习)