Evolution(矩阵快速幂)zoj2853

Evolution

Time Limit: 5 Seconds      Memory Limit: 32768 KB

 

Description

Evolution is a long, long process with extreme complexity and involves many species. Dr. C. P. Lottery is currently investigating a simplified model of evolution: consider that we have N (2 <= N <= 200) species in the whole process of evolution, indexed from 0 to N-1, and there is exactly one ultimate species indexed as N-1. In addition, Dr. Lottery divides the whole evolution process into M (2 <= M<= 100000) sub-processes. Dr. Lottery also gives an 'evolution rate' P(i, j) for 2 species i and j, where i and j are not the same, which means that in an evolution sub-process, P(i, j) of the population of species i will transform to species j, while the other part remains unchanged.

Given the initial population of all species, write a program for Dr. Lottery to determine the population of the ultimate species after the evolution process. Round your final result to an integer.

 

Input

The input contains multiple test cases!

Each test case begins with a line with two integers NM. After that, there will be a line with N numbers, indicating the initial population of each species, then there will be a number T and T lines follow, each line is in format "i j P(i,j)" (0 <= P(i,j) <=1).

A line with N = 0 and M = 0 signals the end of the input, which should not be proceed.

 

Output

For each test case, output the rounded-to-integer population of the ultimate species after the whole evolution process. Write your answer to each test case in a single line.

Notes

  • There will be no 'circle's in the evolution process.
  • E.g. for each species i, there will never be a path i, s1, s2, ..., st, i, such that P(i,s1) <> 0, P(sx,sx+1) <> 0 and P(st, i) <> 0.
  • The initial population of each species will not exceed 100,000,000.
  • There're totally about 5 large (N >= 150) test cases in the input.

Example

Let's assume that P(0, 1) = P(1, 2) = 1, and at the beginning of a sub-process, the populations of 0, 1, 2 are 40, 20 and 10 respectively, then at the end of the sub-process, the populations are 0, 40 and 30 respectively.

 

Sample Input

 

2 3
100 20
1
0 1 1.0
4 100
1000 2000 3000 0
3
0 1 0.19
1 2 0.05
0 2 0.67
0 0

 

Sample Output

 

120
0

 

 

题意:就是说物种进化,有N种物种,编号是0-----N-1,M次进化后,问你编号为N-1的物种有多少数量;

其中要注意的就是i物种进化到j物种的概率是p;(那么剩下的不要忘了);所以单位矩阵初始化对角线的值为1,

然后根据题目进化的概率进行加减;比如P(i, j) = 0.3,则mat[i][j] += 0.3,mat[i][i] -= 0.3;

       把题目转化为数学模型,分析后就是 有一个初始序列, 有一个进化率矩阵,求的是初始序列 与进化率矩阵进

行 m 次运算后, 初始序列最后一位的答案,那么显然,可以对进化率矩阵进行快速幂计算

 

  这里,有一点是要注意的 由于矩阵的大小是200*200的但是一般的笔记本内存不够,至少我的笔记本不

行。。。。。以至于本人纠结了N久,,,谁让题目是服务器改的呢。。。。!<Memory Limit: 32768 KB>

内存就是大!

不说了,其他的都是比较基础的。

转载请注明出处:http://www.cnblogs.com/yuyixingkong/p/4326818.html

题目来源:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1853

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;


int N,M;struct matrix
{
    double mat[210][210];
};

double num[210];


matrix multiply(matrix x,matrix y)//
{
    matrix temp;
    memset(temp.mat,0,sizeof(temp.mat));
    for(int i=0; i<N; i++)
    {
        for(int j=0; j<N; j++)
        {
            if(x.mat[i][j]==0) continue;
            for(int k=0; k<N; k++)
            {
                if(y.mat[j][k]==0) continue;
                temp.mat[i][k]+=x.mat[i][j]*y.mat[j][k];
            }
        }
    }
    return temp;
}

matrix quicklymod(matrix a,int n)
{
    matrix res;//单位阵
    memset(res.mat,0,sizeof(res.mat));
    for(int i=0;i<N;i++) res.mat[i][i]=1;
    while(n)
    {
        if(n&1)
            res=multiply(res,a);
        n>>=1;
        a=multiply(a,a);
    }
    /*for(int i=0; i<N; i++)
        {
            for(int j=0; j<N; j++)
                printf("%5.2lf",a.mat[i][j]);
            printf("\n");
        }
        printf("\n");*/
    return res;
}
int main()
{
    int i,j,T;
    double p,ans;
    matrix ant;
    while(scanf("%d%d",&N,&M),(N||M))
    {
        for(i=0;i<N;i++)
        {
            scanf("%lf",&num[i]);
            for(j=0;j<N;j++)
            {
                if(i==j)
                    ant.mat[i][j]=1;
                else
                    ant.mat[i][j]=0;
            }
        }

        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%lf",&i,&j,&p);
            ant.mat[i][j]+=p;
            ant.mat[i][i]-=p;
        }

        ant=quicklymod(ant,M);

        ans=0;
        for(i=0;i<N;i++)
        {
            ans+=num[i]*ant.mat[i][N-1];
        }
        printf("%.0lf\n",ans);
    }
    return 0;
}


/*
2 3
100 20
1
0 1 1.0
4 100
1000 2000 3000 0
3
0 1 0.19
1 2 0.05
0 2 0.67
0 0
*/

 

posted @ 2015-03-10 18:56  寻找&星空の孩子  阅读(604)  评论(0编辑  收藏  举报