"蔚来杯"2022牛客暑期多校训练营2 K/L补题
作者:互联网
"蔚来杯"2022牛客暑期多校训练营2
K Link with Bracket Sequence I
题目大意:给定一个长度为\(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个左括号未匹配的方案数 \]定义状态:
\[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] \]\(b\)多放一个右括号
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;
}
L Link with Level Editor I
题目大意:有\(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