LYK 与实验室(lab) DP+滚动数组

Time Limit:5000ms Memory Limit:64MB

题目描述

LYK 在一幢大楼里,这幢大楼共有 n 层,LYK 初始时在第 a 层上。
这幢大楼有一个秘密实验室,在第 b 层,这个实验室非常特别,对 LYK 具有约束作用,
即若 LYK 当前处于 x 层,当它下一步想到达 y 层时,必须满足|x-y|<|x-b|,而且由于实验室
是不对外开放的,电梯无法停留在第 b 层。
LYK 想做一次旅行,即它想按 k 次电梯,它想知道不同的旅行方案个数有多少个。
两个旅行方案不同当前仅当存在某一次按下电梯后停留的楼层不同。

输入格式(lab.in)

一行 4 个数,n,a,b,k。

输出格式(lab.out)

一个数表示答案,由于答案较大,将答案对 1000000007 取模后输出。

输入样例 1

5 2 4 1

输出样例 1

2

输入样例 2

5 2 4 2

输出样例 2

2

输入样例 3

5 3 4 1

输出样例 3

数据范围

对于 20%的数据 n,k<=5。
对于 40%的数据 n,k<=10。
对于 60%的数据 n,k<=500。
对于 90%的数据 n,k<=2000。
对于 100%的数据 n,k<=5000。

题解:

DP+滚动数组

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long mod = 1000000007;
int n, a, b, k;
long long ans;
int xl[2333], cs[2333];
bool used[2333], lsu[2333];
long long dp[2][5002], sum[5002];
void dfs(int s, int cnt)
{
	if (cnt == k)
	{
		ans++;
		ans %= mod;
		return ;
	}
	int x = abs(s - b);
	for (int i = 1; i < x; i++)
	{
		if (s+i == b || s-i == b)
			continue;
		if (s+i <= n)
			dfs(s+i, cnt+1);
		if (s-i >= 1)
			dfs(max(s-i, 1), cnt+1);
	}
}
int main()
{
	cin >> n >> a >> b >> k;
	if (k <= 10)
	{
		ans = 0;
		dfs(a, 0);
		cout << ans%mod << endl;
	}
	else
	{
		if (a >= b)
			n -= b, a -= b;
		else
			n = b-1, a = b - a;
		dp[0][a] = 1;
		for (int i = 1; i <= k; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				sum[j] = sum[j-1] + dp[(i+1)%2][j];
				sum[j] %= mod;
			}
			for (int j = 1; j <= n; j++)
			{
				int ls = i % 2;
				dp[ls][j] = sum[n] - sum[j];
				int p = j/2;
				dp[ls][j] += sum[j-1] - sum[p];
				while (dp[ls][j] < 0)
					dp[ls][j] += mod;
				dp[ls][j] %= mod;
			}
		}
		ans = 0;
		k%=2;
		for (int i = 1; i <= n; i++)
		{
			ans += dp[k][i];
			while (ans < 0)
				ans += mod;
			ans %= mod;
		}
		cout << ans;
	}
	return 0;
}

 

上一篇
下一篇