【HDU6146】【2017百度之星复赛-C】Pokémon GO(动态规划)(dp)
2017-08-19 12:23
225 查看
题目大意:
有一个2×N(1≤N≤10000)的网格,从任意一格出发,每次走相邻的格子,可以横着,竖着,斜着走,问用最少的步数走完所有格子的方案数。题解:
最少的步数,即为不重复走任何一个格子。枚举第一步从哪一列出发,先走完左边或右边所有格子后,再走另一边,将两边的方案数相乘。如下图:
用动态规划来计算走完一边的方案数,要分两种情况:
1.走完一边不用回到出发的一列(但包含回到出发列的方案);
2.走完一边要回到出发的那一列。
dp[i][0]表示第一种情况的方案数;
dp[i][1]表示第二种情况的方案数。
也可以这样理解:
第一种情况表示:
第二种情况表示:
第一种情况转移:
只走一列:
走两列:
用下面第二种情况来走
第二种情况转移:
这时,每一列只能选一格来走,这样当往右走到底时,才能有空位回来
dp[i][0]=dp[i-1][0]*2+dp[i-2][0]*4+dp[i-1][1]*2;
dp[i][1]=dp[i-1][1]*2;
计算结果时,枚举起始的每一列,加上左边的方案数*右边的方案数*2。(这一列有两个格子可以选择)
ans+=dp[i-1][1]*dp[n-i[0]*2+dp[n-i][1]*dp[i-1][0]*2;
从第一列或最后一列出发需单独处理。
n=1时特判。
代码:
#include<cstdio> #include<cstring> const int MAXN=10005; const long long MOD=1000000007LL; int dp[MAXN][2]; int main() { int T,n; long long ans; dp[0][0]=1; dp[0][1]=1; dp[1][0]=2; dp[1][1]=2; for(n=2;n<=10000;n++) { dp [0]=((dp[n-1][0]*2LL)%MOD+(dp[n-1][1]*2LL)%MOD+(dp[n-2][0]*4LL)%MOD)%MOD; dp [1]=(dp[n-1][1]*2LL)%MOD; } scanf("%d",&T); while(T--) { scanf("%d",&n); if(n==1) printf("2\n"); else { ans=0; ans=(ans+dp [0])%MOD; for(int i=2;i<n;i++) { ans=(ans+(2LL*dp[i-1][1]*dp[n-i][0])%MOD)%MOD; ans=(ans+(2LL*dp[n-i][1]*dp[i-1][0])%MOD)%MOD; } ans=(ans+dp [0])%MOD; printf("%I64d\n",ans); } } return 0; }
相关文章推荐
- HDU6146(2017百度之星程序设计大赛 - 复赛)[Pokémon GO]--DP
- 2017百度之星复赛:1003. Pokémon GO(递推)
- Hdu6146 Pokémon GO(2017百度之星程序设计大赛 - 复赛)
- HDU 6146 && 2017 百度之星复赛 1003 Pokémon GO(递推)
- 百度之星复赛--Pokémon GO----dp
- 2017百度之星复赛 1003 Pokémon GO 递推
- HDU6147(2017百度之星程序设计大赛 - 复赛)[Pokémon GO II]--找规律
- HDU-2017"百度之星"程序设计大赛-复赛-1003-Pokémon GO
- 2017百度之星复赛 hdu 6148 Valley Numer (数位dp)
- HDU6146 Pokémon GO【DP】
- 2017百度之星复赛:1006. Valley Numer(数位DP)
- HDU 6148 && 2017 百度之星复赛 1005 Valley Numer(数位dp)
- 2017 百度之星 复赛 Valley Numer(数位dp)
- 计蒜客 2017 复赛 腾讯消消乐 (状压dp)
- [2017百度之星程序设计大赛- 复赛] C - hdu6146
- 2017 百度之星复赛题解 01、03、05
- hdu 6146 Pokémon GO(DP)
- HDU 5713 K个联通块 状压dp枚举子集 (2016百度之星复赛)
- 计蒜之道 2017 程序设计大赛 - 计蒜客 复赛 F 腾讯消消乐 状态压缩dp、枚举+剪枝
- 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】