[蓝桥杯 2013 国 B] 格子刷油漆

[蓝桥杯 2013 国 B] 格子刷油漆_第1张图片

解题思路: 一眼顶真,鉴定为动态规划。先考虑从第一行某个位置进入(第二行对称,直接乘二)。

如果是第一行的边界,假如是左边第一个:

①直接向下走,然后跳到右边,有两种情况(右和右上),之后就是已任何点为终点的路径数。

②直接跳到右边,有两种情况,然后终点固定(否则不能填满),这也需要维护个数组。

如果不是边界:

①不能直接向下走,选左边或右边开始,且必须终点固定,返回后到另一边,终点不固定。

其实还有一个注意点,如果右边(左边也类似)列数大于2,可以先跳到右边,再跳到左下方,再跳到右边(两种方案),再终点不固定。

详情见代码。

#include 
using namespace std;
typedef long long ll;
const int N=1e3+5;
int mod=1e9+7;
ll f1[N],f[N];
int main( )
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;cin>>n;
    f1[1]=1;f[1]=1;
    for(int i=2;i<=n;i++)
    {
        f1[i]=(f1[i-1]*2)%mod;
    }
    ll ans=0;
    for(int i=2;i<=n;i++)
    {
        f[i]=(2*f[i-1]+2*f1[i-1])%mod;
        if(i-2>0)
        f[i]=(f[i]+4*f[i-2])%mod;
        else if(i-2==0)f[i]+=2;
    }
    for(int i=1;i<=n;i++)
    {
        int l=i-1,r=n-i;
        if(i==1)
        {
            ans+=2*f[r]+2*f1[r];ans%=mod;
            if(r-1>=1)ans=(ans+4*f[r-1])%mod;
            else if(r-1==0)ans+=2;
            continue;
        }
        if(i==n)
        {
            ans+=2*f[l]+2*f1[l];ans%=mod;
            if(l-1>=1)ans=(ans+4*f[l-1])%mod;
            else if(l-1==0)ans+=2;
            continue;
        }
        ans=(ans+2*f[l]*2*f1[r]%mod+2*f[r]*2*f1[l]%mod)%mod;
    }
    cout<<(ans*2)%mod;
    return 0;
}

你可能感兴趣的:(蓝桥杯,蓝桥杯,算法,c++)