UVa 11982 - Fantasy Cricket (dp)

题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=3133&mosmsg=Submission+received+with+ID+26662619

如果该位置为 \('D'\),说明这个位置应该向前放,如果为 \('U'\),则说明应该向后放,如果为 \('E'\),则说明原地不动

于是可以设计出状态,\(dp[i][j]\) 表示前 \(i\) 个人,有 \(j\)\(U\) 的位置还没有放下,转移分之前的 \('U'\) 放不放在当前位置来讨论

转移方程为 :

\[ \begin{cases} dp[i][j] = dp[i-1][j], &s[i] == 'E' \\ dp[i][j] = dp[i-1][j] * j + dp[i-1][j-1], &s[i] == 'U' \\ dp[i][j] = dp[i-1][j] * j + dp[i-1][j+1] * (j+1) * (j+1), &s[i] == 'D' \end{cases} \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 1010;
const int M = 1000000007;

int T, n;
int dp[maxn][maxn];
char s[maxn]; 

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	scanf("%d", &T);
	for(int kase = 1 ; kase <= T ; ++kase){
		scanf("%s", s + 1);
		n = strlen(s + 1);
		memset(dp, 0, sizeof(dp));
		
		dp[0][0] = 1;
		for(int i = 1 ; i <= n ; ++i){
			for(int j = 0 ; j <= i ; ++j){
				if(s[i] == 'E'){
					dp[i][j] = dp[i-1][j];
				} else if(s[i] == 'U'){
					dp[i][j] = 1ll * dp[i-1][j] * j % M;
					if(j > 0) dp[i][j] = (dp[i][j] + dp[i-1][j-1]) % M;
				} else{
					dp[i][j] = (1ll * dp[i-1][j] * j % M + 1ll * dp[i-1][j+1] * (j+1) % M * (j+1) % M) % M;
				}
			}
		} 
		
		printf("Case %d: %d\n", kase, dp[n][0]); 
	}
	return 0;
}
posted @ 2021-08-07 16:06  Tartarus_li  阅读(28)  评论(0编辑  收藏  举报