ZOJ --- 2974 倒水 【思维 + 矩阵快速幂】

来源:互联网 发布:采购平台软件 编辑:程序博客网 时间:2024/05/23 02:17

传送门

题意 : 就是给你N个瓶子, 每一分钟依次对每一个瓶子进行操作, 分别是将该个瓶子里的水, 倒入所给的瓶子里去, 一共持续m分钟, 最后输出每一个瓶子里的水.
思路 : 不好一眼看出来是矩阵的思想, 这是就需要把样例进行推导, 的然后就可以写出来两个矩阵相乘, 最后得到的就是一个其他矩阵, 所以这道题就是矩阵快速幂. 特别注意下当k等于0时对瓶子的操作.

AC 代码:

#include<bits/stdc++.h>#define CLR(x) memset(x,0,sizeof(x))#define db double#define ll long longusing namespace std;int ssize;struct Ma{    db a[25][25];    void cc(){        CLR(a);    }    Ma operator * (const Ma & b) const {        Ma tmp;        tmp.cc();        for(int i=1;i<=ssize;i++){            for(int j=1;j<=ssize;j++){                for(int k=1;k<=ssize;k++){                    tmp.a[i][j] += a[i][k] * b.a[k][j] ;                }            }        }        return tmp;    }}res,x;void qpow(int m){    res.cc();    for(int i=1;i<=ssize;i++)        res.a[i][i]=1;    while(m)    {        if(m&1) res = res * x;        x = x* x ;        m >>= 1 ;    }}db s[25],result[25];int main(){    int t;    cin >> t;    while(t--){        int n;        cin >> n;        ssize = n;        CLR(s);        CLR(result);        for(int i=1;i<=n;i++)            cin >> s[i];        x.cc();        for(int i=1;i<=n;i++){            int k;            cin >> k;            if(!k) x.a[i][i] = 1.0;   //尤其注意下k等于0的时候.            for(int j=0;j<k;j++){                int u;                cin >> u;                x.a[i][u] = 1.0/k*1.0;            }        }        int m;        cin >> m;        qpow(m);    //快速幂.        for(int i=1;i<=n;i++){            for(int j=1;j<=n;j++){                result[i] += res.a[j][i] * s[j];            }        }        for(int i=1;i<=n;i++){            printf("%.2f%c",result[i],i==n?'\n':' ');        }    }}