Connecting...

P11230 [CSP-J 2024] 接龙

P11230 [CSP-J 2024] 接龙

关键观察

  1. \(r\) 很小,\(O(nr)\)

  2. \(dp_{r,c}\) 表示第 \(r\) 轮能否以 \(c\) 结尾。注意到限制:“这一轮进行接龙的人不能与上一轮相同”,若 \(dp_{r,c}\) 有大于一种方案,可以忽略限制。

  3. 不妨设

    \[\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)\) 同阶。

posted @ 2025-09-01 11:16  余亦宸  阅读(17)  评论(3)    收藏  举报