HDU6146(2017百度之星程序设计大赛 - 复赛)[Pokémon GO]--DP
2017-08-22 21:45
441 查看
【链接】
hdu6146
【题目大意】
给你一个2∗n的矩阵,你可以从一个格子移动到一个相邻的至少有一个公共点的格子,求从任意一个格子开始遍历所有节点一次的方案数。
【解题报告】
这题其实就是一道DP题就是想转移方程有点复杂。
首先从简单的想,假设求从一个矩阵的一个角遍历所有节点一次且回到同一列的另一个节点的方案数。
那么很容易想到转移方程,定义bi表示目前推到的矩阵大小为2∗i时,满足以上条件的方案数。
b1=1 bi=bi−1∗2(i>1)
所以bi=2i−1
进一步想,假设求从一个矩阵的一个角遍历所有节点一次的方案数。
经过仔细的思考,定义ai表示目前推到的矩阵大小为2∗i时,满足以上条件的方案数。
a1=1 a2=6
所以ai的转移方程就是ai=bi+2∗ai−1+4∗ai−2(i>2)
bi表示已确定已i个列的走法
2∗ai−1表示已确定i−1个列的走法,在增加一列(增加的列不能在开头或末尾),相当于增加两个节点所以就是原来方案数(即ai−1)∗2
4∗ai−2表示已确定i−2个列的走法,在增加相邻两列(增加的列不能在开头或末尾),先遍历前一列的一个点,之后遍历后一列的一个点,再返回前一列遍历另一个点的方案有4种,所以就是原来方案数(即ai−2)∗4
然后就可以推出从2∗n的矩阵的四个角走完遍历所有节点一次的方案数即4∗an
然后就只剩考虑起点不是四个角的情况,我们可以枚举开始的列,定义fi表示以第i列为起点所以转移方程就是
fi=2∗4∗(ai−1∗bn−i+bi−1∗an−i)(1<i<n)
2表示当前列有两个起点可以作为起点,4表示两列之间可以互相走到的方案数。
所以答案就是∑n−1i=2fi+4∗an
hdu6146
【题目大意】
给你一个2∗n的矩阵,你可以从一个格子移动到一个相邻的至少有一个公共点的格子,求从任意一个格子开始遍历所有节点一次的方案数。
【解题报告】
这题其实就是一道DP题就是想转移方程有点复杂。
首先从简单的想,假设求从一个矩阵的一个角遍历所有节点一次且回到同一列的另一个节点的方案数。
那么很容易想到转移方程,定义bi表示目前推到的矩阵大小为2∗i时,满足以上条件的方案数。
b1=1 bi=bi−1∗2(i>1)
所以bi=2i−1
进一步想,假设求从一个矩阵的一个角遍历所有节点一次的方案数。
经过仔细的思考,定义ai表示目前推到的矩阵大小为2∗i时,满足以上条件的方案数。
a1=1 a2=6
所以ai的转移方程就是ai=bi+2∗ai−1+4∗ai−2(i>2)
bi表示已确定已i个列的走法
2∗ai−1表示已确定i−1个列的走法,在增加一列(增加的列不能在开头或末尾),相当于增加两个节点所以就是原来方案数(即ai−1)∗2
4∗ai−2表示已确定i−2个列的走法,在增加相邻两列(增加的列不能在开头或末尾),先遍历前一列的一个点,之后遍历后一列的一个点,再返回前一列遍历另一个点的方案有4种,所以就是原来方案数(即ai−2)∗4
然后就可以推出从2∗n的矩阵的四个角走完遍历所有节点一次的方案数即4∗an
然后就只剩考虑起点不是四个角的情况,我们可以枚举开始的列,定义fi表示以第i列为起点所以转移方程就是
fi=2∗4∗(ai−1∗bn−i+bi−1∗an−i)(1<i<n)
2表示当前列有两个起点可以作为起点,4表示两列之间可以互相走到的方案数。
所以答案就是∑n−1i=2fi+4∗an
#include<cstdio> #define LL long long using namespace std; const int maxn=10005,tt=1000000007; int T,n,ans,a[maxn],b[maxn]; inline int Read() { int res=0; char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') res=res*10+ch-48,ch=getchar(); return res; } void Work() { n=Read(); if (n==1) {printf("2\n"); return;} ans=(LL)4*a %tt; for (int i=2; i<n; i++) ans=(((LL)ans+(LL)8*b[i-1]%tt*a[n-i]%tt)%tt+(LL)8*a[i-1]%tt*b[n-i]%tt)%tt; printf("%d\n",ans); } int main() { freopen("6146.in","r",stdin); freopen("6146.out","w",stdout); b[1]=1; for (int i=2; i<=10000; i++) b[i]=b[i-1]*2%tt; a[1]=1; a[2]=6; for (int i=3; i<=10000; i++) a[i]=(b[i]+(LL)a[i-1]*2+(LL)a[i-2]*4)%tt; T=Read(); while (T--) Work(); return 0; }
相关文章推荐
- 【HDU6146】【2017百度之星复赛-C】Pokémon GO(动态规划)(dp)
- Hdu6146 Pokémon GO(2017百度之星程序设计大赛 - 复赛)
- HDU6147(2017百度之星程序设计大赛 - 复赛)[Pokémon GO II]--找规律
- 百度之星复赛--Pokémon GO----dp
- HDU6147 Pokémon GO II (2017百度之星程序设计大赛 - 复赛)
- 2017百度之星复赛 1003 Pokémon GO 递推
- HDU 6146 && 2017 百度之星复赛 1003 Pokémon GO(递推)
- [2017百度之星程序设计大赛- 复赛] C - hdu6146
- HDU6146 Pokémon GO (2017百度之星程序设计大赛 - 复赛)
- 2017百度之星复赛:1003. Pokémon GO(递推)
- HDU6146 Pokémon GO【DP】
- [递推] HDU6146 Pokémon GO
- [lucas+数位DP] 2017 计蒜之道 复赛 E. 商汤智能机器人
- 2017百度之星复赛:1006. Valley Numer(数位DP)
- 计蒜之道-2017复赛-腾讯消消乐(状压DP)
- 2017百度之星程序设计大赛 - 复赛 题解(1,3)
- HDU6148 Valley Numer (2017百度之星程序设计大赛 - 复赛)
- 计蒜之道 2017 程序设计大赛 - 计蒜客 复赛 F 腾讯消消乐 状态压缩dp、枚举+剪枝
- 【莫比乌斯反演+数位DP】2017 计蒜之道 复赛 A.阿里云秘钥池
- (状压dp)2017 计蒜之道 复赛 F. 腾讯消消乐