【DP】【NOIP普及组T2】track

题目描述

【题目背景】
Tom又一次地在追Jerry。Jerry跑进了一个神奇的跑道,Tom也跟了进去。Jerry想利用这个跑道让Tom摔倒,这样就不会被追上了。Jerry正在全力奔跑,所以就把这个计算任务交给你了。
【题目描述】
Jerry初始时在地面上的入口处。在跑道入口,以及在跑道中每跑过一秒就会遇到一个分岔口,一边是上坡跑道,一边是下坡跑道,跑道都是通向前方,是不会形成环的。Jerry也没有时间回头看Tom是否追上,所以他只会全力向前奔跑,而不会停下或者向回跑。每一秒在上坡跑道高度会上升1米,在下坡跑道高度会下降1m。Jerry通过告示牌知道这个跑道从入口到每个出口都恰好要跑T秒,也就是恰好在跑过T秒后就没有分岔口,出跑道了。Jerry也知道Tom会摔倒当且仅当它跑过了一段特定的上坡下坡的路段。Jerry要求在跑完后仍然在地面上(即出口的高度等于入口的高度)。不幸的是,前几天刚下过大雨,地面以下的跑道(即高度小于入口高度的跑道)都有积水,无法通行。Jerry想知道有多少种符合条件的选择跑道的方案(即有多少个出口对应的路径)能让Tom在这过程中摔倒,结果对1000000007取模。
输入
第一行一个正整数T,表示Jerry跑道上的时间。第二行一个仅有字母‘D’和‘U’构成的字符串S,表示Tom要摔倒的话要连续经过这样一段上下坡的路径,其中‘D’表示下坡,‘U’表示上坡。
输出
一行一个整数,表示符合条件且能让Tom摔倒的选择跑道的方案数对1000000007取模后的结果。
样例输入

【输入样例1】
2
UD
【输入样例2】
6
DDU

【输出样例1】
1
【输出样例2】
1

数据范围限制
对于50%的数据,1≤|S|≤T≤16。
对于另外10%的数据,T是奇数。
对于100%的数据,1≤|S|≤T≤200,S仅由‘U’和‘D’构成。


思路

一开始还想要暴搜,当我打完后,突然发现要去重。。。(机房惨案

g [ i , j ] g[i,j] 为第 i i 秒高度为 j j 的最优解,最后输出 g [ n , 0 ] g[n,0]
为了判重,我们要设一个 f [ i , j ] f[i,j] 为第 i i 秒高度为 j j 的最优解 (吧)
但是因为有特定的一段高度,so,我们的 g g 要多加一些东西
举个栗子:
DDDUU

  • down了三次,那必须在高度大于等于3的地方转移过来
  • down的长度为3,那么时间就用了3
  • 最后高度为-1,那么高度就要从 高度+(-1)转移过来

那么g的转移方程还有

for(int j=3;j<=i;j++)
	g[i+3][j+(-1)]+=f[i][j]-g[i][j];//-g[i][j]是因为在之前"这一段特定高度"已经做过了,简称“判重”

#include<iostream>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
const int mo=1000000007;//一定要记得%
long long f[1000][1000],g[1000][1000];
int n,m,d,m1;
string s;
int main(){
	//freopen("track.in","r",stdin);
	//freopen("track.out","w",stdout);
	scanf("%d",&n);
	cin>>s;
	int d=0;
	for(int i=0;i<s.size();i++){
		if(s[i]=='D')d--;
		   else d++;
		m1=max(m1,-d);
	}
	f[0][0]=1;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=i;j++){
			if(j>0)f[i][j]=f[i-1][j-1],g[i][j]=(g[i][j]+g[i-1][j-1])%mo;
			if(i>0)f[i][j]=(f[i-1][j+1]+f[i][j])%mo,g[i][j]=(g[i-1][j+1]+g[i][j])%mo;
		}
		for(int j=m1;j<=i;j++)
		    g[i+s.size()][j+d]=(g[i+s.size()][j+d]+f[i][j]-g[i][j])%mo;
	}
	printf("%lld",g[n][0]);
}
发布了45 篇原创文章 · 获赞 0 · 访问量 381

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/102733342