P11230 [CSP-J 2024] 接龙
P11230 [CSP-J 2024] 接龙
关键观察
-
\(r\) 很小,\(O(nr)\)
-
\(dp_{r,c}\) 表示第 \(r\) 轮能否以 \(c\) 结尾。注意到限制:“这一轮进行接龙的人不能与上一轮相同”,若 \(dp_{r,c}\) 有大于一种方案,可以忽略限制。
-
不妨设
\[\begin{equation} \begin{aligned} dp_{r,c}= \begin{cases} -1 &0种方案,不可至\\ 0& \text{多种方案,即下一步任意接} \\ x& \text{从x这个人接过来,下一步不能用x,其余任意接}\\ \end{cases} \end{aligned} \end{equation} \]
考虑转移:当 \(dp_{r-1,c}=i\) 时 可以对 不等于 \(i\) 的人,以 \(c\) 开头的后 \(k-1\) 个接龙。
当 \(dp_{r-1,c}=0\) 时 可以对任何的人,以 \(c\) 开头的后 \(k-1\) 个接龙。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,R=1e2+2;
int n,k,q,dp[R][N];
vector<int>v[N];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
int t;cin>>t;
while(t--){
cin>>n>>k>>q;
for(int i=1;i<=n;++i){
v[i].clear();
int l,s;cin>>l;
while(l--) cin>>s,v[i].push_back(s);
}
for(int i=0;i<R;++i) for(int j=1;j<N;++j) dp[i][j]=-1;
dp[0][1]=0;
for(int r=1;r<R;++r){
for(int i=1;i<=n;++i){
int cnt=0;//多少个可被接龙的数
for(auto c:v[i]){
if(cnt>0){
if(dp[r][c]==-1) dp[r][c]=i;
else if(dp[r][c]!=i) dp[r][c]=0;
cnt--;
}
if(dp[r-1][c]!=-1&&dp[r-1][c]!=i) cnt=k-1;
}
}
}
while(q--){
int r,c;cin>>r>>c;
cout<<(dp[r][c]>=0)<<"\n";
}
}
return 0;
}
最后复杂度是 \(O(r\sum{l})\),与 \(O(n,r)\) 同阶。

浙公网安备 33010602011771号