很明显从右下角的盒子下面出去的球的个数只与最后一列最下面那个切换器有关。我们可以把每一个切换器看作一个节点。每个节点向它的子节点输送它自身一半的球(如果是奇数个要判断哪个子节点得到的更多)。遍历一遍就能得到结果
遍历是n^2的,所以我们需要o(1) 找它的父节点,否则会超时。
具体看代码吧
#include<stdio.h>
using namespace std;
typedef long long ll;
ll a[1010][1010];
ll f[1010][1010];
ll up[1010][1010];
ll le[1010][1010];
ll l[1010];
ll u[1010];
int main(){
ll n, m, k;
scanf("%lld%lld%lld", &m, &n, &k);
f[1][1] = k;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%lld", &a[i][j]);
if(a[i][j] != 0){
if(a[1][1] == 0 && j == 1){
a[1][1] = -1;
u[1] = 1;
f[1][1] += k;
}
le[i][j] = l[i];
l[i] = j;
up[i][j] = u[j];
u[j] = i;
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i][j] != 0){
int x = up[i][j];
int y = le[i][j];
if(f[x][j] % 2 && a[x][j] == -1){
f[i][j] += f[x][j] / 2 + 1;
}else f[i][j] += f[x][j] / 2;
if(f[i][y] % 2 && a[i][y] == 1){
f[i][j] += f[i][y] / 2 + 1;
}else f[i][j] += f[i][y] / 2;
}
}
}
if(f[u[m]][m] % 2 && a[u[m]][m] == -1)
printf("%lld\n", f[u[m]][m] / 2 + 1);
else printf("%lld\n", f[u[m]][m] / 2);
return 0;
}