zoj 2974 Just Pour the Water (矩阵快速幂,简单)
对于案例的解释请见下图:
这道要变动提取一下矩阵,之后就简单了
具体解释可看代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <string.h> #include <stdio.h> #include<algorithm> using namespace std; int num; struct matrix { double a[30][30];//把每次倒水的比率提取出来放在这里面,例如i倒给j几分之几,以便进行计算 }origin,answ;//answ保存提取出来比率计算后的答案 matrix multiply(matrix x,matrix y)//x与y的矩阵乘法 { matrix temp; for(int i=1;i<=num;i++) { for(int j=1;j<=num;j++) { double ans=0; for(int k=1;k<=num;k++) { ans+=x.a[i][k]*y.a[k][j]; } temp.a[i][j]=ans; } } return temp; } matrix calc(int n)//矩阵快速幂——把提取出来的比率进行n次重复的‘倒’,即n次幂 { while(n)//以下运用二分 { if(n%2==1) answ=multiply(origin,answ); origin=multiply(origin,origin); n/=2; } return answ; } int main() { int t,n,k,m; double a[30]; scanf("%d",&t); for(int id=0;id<t;id++) { memset(answ.a,0,sizeof(answ.a)); memset(origin.a,0,sizeof(origin.a)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf",&a[i]); num=n; for(int i=1;i<=n;i++) answ.a[i][i]=1; for(int i=1;i<=n;i++) { scanf("%d",&k);//i要平均的倒给之后的k个人 if(k==0) origin.a[i][i]=1.0;//不向任何地方倒,相当于都倒给自己,即1/1 for(int j=1;j<=k;j++) { int p; scanf("%d",&p); origin.a[p][i]=1.0/k;//i倒给p的比率 } } scanf("%d",&m); calc(m);//对数据进行处理 for(int i=1;i<=n;i++)//逐个输出答案 { double ans=0;//初始化 for(int j=1;j<=n;j++)//一列一列处理 ans+=answ.a[i][j]*a[j];//处理后的比率*原始数据 if(i==1) printf("%.2lf",ans); else printf(" %.2lf",ans); } puts(""); } return 0; }
一道又一道,好高兴!