码迷,mamicode.com
首页 > 其他好文 > 详细

【HDU】6146 Pokémon GO

时间:2017-08-22 18:38:14      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:view   ons   状态   公式   none   计算   display   重要   规划   

【题意】一个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\n",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)

 

【HDU】6146 Pokémon GO

标签:view   ons   状态   公式   none   计算   display   重要   规划   

原文地址:http://www.cnblogs.com/onioncyc/p/7412888.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!