ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

"蔚来杯"2022牛客暑期多校训练营2 K/L补题

2022-07-27 18:33:46  阅读:130  来源: 互联网

标签:int 蔚来 rep 多校 括号 补题 Longrightarrow longrightarrow dp


"蔚来杯"2022牛客暑期多校训练营2

题目大意:给定一个长度为\(n\)的括号序列\(a\),\(a\)是一个长度为\(m\)的合法括号序列\(b\)的子序列,求\(b\)的方案数

(\(mod\ 10^9+7,1 \le n \le m \le 200\) )

解题思路:考虑类似最长公共子序列的动态规划,加上括号序列需要合法的限制

定义状态:

\[dp[i][j][k]:=b的前i个最多匹配a的前j个,剩下k个左括号未匹配的方案数 \]

状态转移:

\(b\)多放一个左括号

\[a_{j+1}==')'\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j][k+1]\\ a_{j+1}=='('\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j+1][k+1] \]

\(b\)多放一个右括号

\[a_{j+1}=='('\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j][k-1]\\ a_{j+1}==')'\ \ \Longrightarrow \ \ dp[i][j][k]\longrightarrow dp[i+1][j+1][k-1] \]

AC代码:

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

#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)

const int N = 210, MOD = 1e9 + 7;

int dp[N][N][N];
char a[N];

void work() {
	int n,m;
	cin>>n>>m>>a+1;
	
	memset(dp,0,sizeof dp);
	dp[0][0][0]=1;
	
	rep(i,0,m-1){
		rep(j,0,min(i,n)){
			rep(k,0,i){
				// '('
			    if(a[j+1]=='(') dp[i+1][j+1][k+1]=(dp[i+1][j+1][k+1]+dp[i][j][k])%MOD;	
				else dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k])%MOD; 	 		 
				// ')'
				if(!k) continue;
				if(a[j+1]==')') dp[i+1][j+1][k-1]=(dp[i+1][j+1][k-1]+dp[i][j][k])%MOD;
				else dp[i+1][j][k-1]=(dp[i+1][j][k-1]+dp[i][j][k])%MOD;
			}
		}
	}
	
	cout<<dp[m][n][0]<<endl;
}

signed main() {
	int test=1;
	cin >> test;
	
	while (test--) 
		work();
	
	return 0;
}

题目大意:有\(n\)个世界,每个世界是一个\(m\)个点的无向图。选择一个世界从其编号为\(1\)的起点出发,每个世界可以不动或者走一条边到达下一个点\(u\),然后跳到下一个世界的点\(u\),如果跳到点\(m\)则胜利。求一个可以获胜的最短连续子段。

(\(1<=n<=10^4,2<=m<=2*10^3 ,ML=32MB\))

解题思路:考虑\(bfs\)或者\(dp\)或者乱搞,这里给出\(dp\)的做法。因为有空间限制,\(dp\)需要用滚动数组优化。

定义状态:

\[dp[i][j]:=最大的k,可以从第k个世界编号为1的点到达第i个世界编号为j的点 \]

状态转移:

\[dp[i+1][1]=i+1\\dp[i+1][v]=_{max_{u\longrightarrow\ v}}\ dp[i][u] \]

AC代码:

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

#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int N = 2e5 + 10;

int dp[2][N];

void work() {
	memset(dp,-1,sizeof dp);
	int n,m;
	cin>>n>>m;
	
	int ans=INF;
	rep(i,1,n){
		dp[0][1]=i;
		
		int k;
		cin>>k;
		while(k--){
			int a,b;
			cin>>a>>b;
			dp[1][b]=max(dp[1][b],dp[0][a]);
		}
		
		if(dp[1][m]!=-1) ans=min(ans,i-dp[1][m]+1);
		rep(j,1,m) dp[0][j]=dp[1][j];
	}
	
	if(ans==INF) cout<<-1<<endl;
	else cout<<ans<<endl;	
}

signed main() {
	IO
	int test=1;
	
	while (test--) 
		work();
    
	return 0;
}

标签:int,蔚来,rep,多校,括号,补题,Longrightarrow,longrightarrow,dp
来源: https://www.cnblogs.com/xhy666/p/16525890.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有