管道维修
n*m个格子,每个格子有(p_{ij})的概率堵上。如果一个格子堵上了,那么清理它需要一步。只有当一个格子与外部相联通且被疏通时,你可以去清理它周围的格子。问每一个格子被清理完的期望步数。
颠覆了我对期望题的认知……原来此题非期望dp,而是直接从期望的定义出发。(n^3)预处理即可。
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=205, mod=1e9+7;
int n, m;
LL p[maxn][maxn], E[maxn][maxn];
int f[maxn][maxn][maxn];
int fpow(int a, int x){
LL base=a, ans=1;
for (; x; x>>=1, (base*=base)%=mod)
if (x&1) (ans*=base)%=mod;
return ans;
}
int inv(int x){ return fpow(x, mod-2); }
int P(int x, int y){ return x<0||y<0?0:p[x][y]; }
int main(){
scanf("%d%d", &n, &m); int a, b;
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j){
scanf("%d%d", &a, &b);
p[i][j]=f[i][j][0]=E[i][j]=1ll*a*inv(b)%mod; }
for (int k=1; k<=max(n, m)/2; ++k)
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
f[i][j][k]=1ll*f[i-1][j][k-1]*f[i+1][j][k-1]%mod
*P(i, j-k)%mod*P(i, j-k+1)%mod*P(i, j+k)%mod*P(i, j+k-1)%mod*inv(k>2?f[i][j][k-2]:p[i][j])%mod,
E[i][j]+=f[i][j][k], E[i][j]%=mod;
for (int i=1; i<=n; ++i){
for (int j=1; j<=m; ++j)
printf("%lld ", E[i][j]);
puts(""); }
return 0;
}