http://codeforces.com/problemset/problem/479/E
不难看出是dp,令dp[i][j]表示i步后到达j位置的方案数。但是在进行状态转移时,如果不优化,复杂度太高会超时。而又不难发现状态转移所需的上一层的条件都是连续的片段。于是可以用前缀数组优化
注意点:
- 不能连续两次都在同一层,所以要减去dp[i-1][j]。
- 注意如果某一点到b和j的距离相等,则下一步不能到达j。
- 题目涉及到取余数,如果可能为负的话需要加一次mod再取余。
- -
#include <iostream>
#include <cmath>
#include <cstring>
#include <stdio.h>
using namespace std;
//#define mod 1e9+7
const int mod=1e9+7;
int n,a,b,m;
int dp[5005][5005];//dp[i][j]表示i步后到达j位置的方案总数
int pre[5005];//pre[j]记录前一轮中到达前j个点(包括j)的方案总数
int main()
{
scanf("%d%d%d%d",&n,&a,&b,&m);
memset(dp,0,sizeof(dp));
dp[0][a]=1;
for(int i=1; i<=m; i++)
{
pre[0] = 0;
for(int j=1; j<=n; j++)
pre[j] = (pre[j-1] + dp[i-1][j])%mod;
for(int j=1; j<=n; j++)
{
if(j==b)
continue;
if(j<b)
dp[i][j] = (pre[(b+j-1)/2])%mod;
else
dp[i][j] = (pre[n] - pre[(b+j)/2] + mod)%mod;
dp[i][j] = (dp[i][j] - dp[i-1][j] + mod)%mod;
}
}
int ans=0;
for(int i=1; i<=n; i++)
ans = (ans + dp[m][i])%mod;
printf("%d\n",ans);
return 0;
}