解题思路
不是正解。。
先对于每一个位置,求出这一个位置的极高,例如对于7而言,每一个位置的极高为 0 , 1 , 2 , 3 , 2 , 1 , 0 0,1,2,3,2,1,0 0,1,2,3,2,1,0,对于8而言,每一个位置的极高为 0 , 1 , 2 , 3 , 3 , 2 , 1 , 0 0,1,2,3,3,2,1,0 0,1,2,3,3,2,1,0;
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示到第i个位置,高度为j的方案数,如果当前位置被推倒,
则
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
−
1
]
+
f
[
i
−
1
]
[
j
]
+
f
[
i
−
1
]
[
j
+
1
]
f[i][j]=f[i-1][j-1]+f[i-1][j]+f[i-1][j+1]
f[i][j]=f[i−1][j−1]+f[i−1][j]+f[i−1][j+1].
对于知道当前位置的高度时,上式所有的
j
=
a
[
i
]
;
j=a[i];
j=a[i];
要开滚动数组,否则会炸。。
(正解:数论题,我可能会吗??)
代码
#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
const int mod=1e9+7;
int n,t,tt,a[20010];
long long f[2][10010];
int h(int x)
{
if(x<(n/2+1))return x-1;
return n-x;
}
int main(){
freopen("brick.in","r",stdin);
freopen("brick.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
f[0][0]=1;
for(int i=1;i<=n;i++)
{
t=h(i);
tt=h(i-1);
if(a[i]!=-1)
{
if(a[i]<=t)
{
f[1][a[i]]+=f[0][a[i]];
if(a[i]>=1)f[1][a[i]]+=f[0][a[i]-1];
if(a[i]+1<=tt)f[1][a[i]]+=f[0][a[i]+1];
if(i%10==0)f[1][a[i]]%=mod;
}
}
else
{
for(int j=0;j<=t;j++)
{
f[1][j]+=f[0][j];
if(j>=1)f[1][j]+=f[0][j-1];
if(j+1<=tt)f[1][j]+=f[0][j+1];
if(i%10==0)f[1][j]%=mod;
}
}
memcpy(f[0],f[1],sizeof(f[1]));
memset(f[1],0,sizeof(f[1]));
}
printf("%lld",f[0][0]%mod);
}