zoukankan      html  css  js  c++  java
  • 【HDU】6146 Pokémon GO

    【题意】一个2*n的网格,再保证步数最少的情况下,求从任意格出发遍历完所有格的方案数,格子八连通。n<=10000,T<=100。

    【算法】递推,DP

    【题解】原题链接:蓝桥杯 格子刷油漆(动态规划)

    这类题目最重要的是找到一个可以计算所有情况的状态表示。

    对于2*x的网格,a[x]表示从左上角出发遍历完所有格子的方案数,b[x]表示从左上角出发遍历完所有格子并在左下角结束的方案数。

    显然,b[x]=2*b[x-1]

    先考虑起点在左上角,有三种情况:

    ①先走到对面(左下角),再往右走,a[x]+=2*a[x-1]。

    ②终点在对面,a[x]+=b[x]。

    ③先走到第二列再折返再走到第二列,此时等价于第二列的第一种情况,a[x]+=4*a[x-2]。

    公式合并为a[x]=2*a[x-1]+4*a[x-2]+b[x]

    一共有四个角,所以ans+=4*a[x]。

    再考虑起点在第一行(不包括左右上角),必须要先遍历完一边回到下方再遍历另一边才能保证遍历完全部。

    对于先遍历一边的情况,等价于出发后回到下方的b[i],再遍历另一边的情况,等价于从一角出发的a[i]。

    所以对于每个中间点i,ans+=2*(2*b[i-1]*2*a[n-i])+2*(2*b[n-i]*2*a[i-1]) 。

    ans=16*sigma(b[i-1]*a[n-i])(i=2~n-1)+4*a[n]

    ---

    有取模别写“+=”!

    爆long long了要中间多写点取模……2*int是撞在ll枪口上的,多一点就爆了。

    ---

    #include<cstdio>
    #define ll long long
    const int maxn=10010,MOD=1000000007;
    ll a[maxn],b[maxn],n;
    int main(){
        b[1]=1;
        for(int i=2;i<=maxn;i++)b[i]=(b[i-1]*2)%MOD;
        a[1]=1;a[2]=6;
        for(int i=3;i<=maxn;i++)a[i]=(2*a[i-1]+b[i]+4*a[i-2])%MOD;
        int T;
        scanf("%d",&T);
        while(T--){
            int n;
            scanf("%d",&n);
            ll ans=0;
            for(int i=2;i<=n-1;i++)ans=(ans+16*b[i-1]%MOD*a[n-i])%MOD;
            ans=(ans+4*a[n])%MOD;
            if(n==1)ans=2;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    能把这个公式换成一个数组的递推公式真是太可怕了。

    f[1]=2  f[2]=24  f[3]=96  f[4]=416  f[5]=1536

    f[i]=f[i-1]*6-f[i-2]*8-f[i-3]*8+f[i-4]*16  (i>=6)

  • 相关阅读:
    团购倒计时
    折半查找
    比较函数
    行为驱动开发: Cucumber的目录结构和执行过程 (转载)
    ruby 方法查找 and执行方法
    Rubyinstance_variable_get(@xx)
    Ruby 模块
    散列
    ruby webdriver 启动firefox driver时,加载firebug的扩展
    git使用简介
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7412888.html
Copyright © 2011-2022 走看看