[bzoj3317]First Knight

建立方程后直接高斯消元,再把0的区间找出来计算,就可以过(因为实际上这样的复杂度是5次的,且常数小)
(当然这样的复杂度看上去并不太好,考虑优化)
可以发现最后一行的概率都可以用上一行来表示,那么代入上一行的方程后,发现又可以再次代入,最后就求出了第一行

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,n,m,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
 4 double f[2005][2005];
 5 int id(int x,int y){
 6     if ((x<1)||(y<1)||(x>n)||(y>m))return 0;
 7     return (x-1)*m+y;
 8 }
 9 double guess(){
10     for(int ii=n;ii;ii--){
11         for(int i=id(ii,1);i<=id(ii,m);i++){
12             double s=abs(f[i][i]);
13             for(int j=i+1;j<=id(ii,m);j++)s=max(s,abs(f[j][i]));
14             for(int j=i;j<=id(ii,m);j++)
15                 if (s==abs(f[j][i])){
16                     s=f[j][i];
17                     for(int k=id(ii-1,1);k<=id(ii,m);k++)swap(f[j][k],f[i][k]);
18                     swap(f[j][id(n,m)+1],f[i][id(n,m)+1]);
19                     break;
20                 }
21             for(int j=id(ii-1,1);j<=id(ii,m);j++)f[i][j]/=s;
22             f[i][id(n,m)+1]/=s;
23             for(int j=id(ii,1);j<=id(ii,m);j++){
24                 if (j==i)continue;
25                 s=f[j][i];
26                 for(int k=id(ii-1,1);k<=id(ii,m);k++)f[j][k]-=f[i][k]*s;
27                 f[j][id(n,m)+1]-=f[i][id(n,m)+1]*s;
28             }
29         }
30         if (ii==1)return f[1][id(n,m)+1];
31         for(int i=id(ii-1,1);i<=id(ii-1,m);i++)
32             for(int j=id(ii,1);j<=id(ii,m);j++){
33                 for(int k=id(ii-1,1);k<=id(ii-1,m);k++)f[i][k]-=f[i][j]*f[j][k];
34                 f[i][id(n,m)+1]-=f[i][j]*f[j][id(n,m)+1];
35             }
36     }
37 }
38 int main(){
39     while (scanf("%d%d",&n,&m)!=EOF){
40         if ((!n)&&(!m))return 0;
41         memset(f,0,sizeof(f));
42         for(int i=1;i<=n;i++)
43             for(int j=1;j<=m;j++)
44                 f[id(i,j)][id(i,j)]=f[id(i,j)][id(n,m)+1]=-1;
45         for(int k=0;k<4;k++)
46             for(int i=1;i<=n;i++)
47                 for(int j=1;j<=m;j++)
48                     scanf("%lf",&f[id(i,j)][id(i+dx[k],j+dy[k])]);
49         f[id(n,m)][id(n,m)+1]=0;
50         printf("%.8f\n",guess());
51     }
52 }
View Code

 

posted @ 2019-10-24 18:00  PYWBKTDA  阅读(195)  评论(0编辑  收藏  举报