您的位置:首页 > 编程语言 > Go语言

【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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: