目前为止,这应该是代码最短的题解
2026-10-05 20:54:15
发布于:广东
7阅读
0回复
0点赞
你们都写这么长的吗?!
题意
给你 个序列和 次询问,问每次是否可以由 为结尾且恰好进行 轮游戏,且符合题目要求。(题意简化的不好,勿喷)
思路
因为CCF的出题风格,判断为DP
注意到 的取值很小,由此想到可以从这里入手。
可以记DP状态为dp[i][j]为到第i轮时,是否可以以j为结尾。不可以记为-1,有多人可以记为0,只有第 个人可以记为 。
预处理出每一轮,也就只需要循环100次。
然后就可以做到 的查询。
记得有多组样例。
一些细节详见代码。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+9,M=1e2+9;
vector<int> ve[N];
int f[M][N];//记f[i][j]为到第i轮时,是否可以以j为结尾
//不可以为-1,有多人可以为0,只有第i个人可以为i
void solved(){
int n,k,q; cin>>n>>k>>q;
for(int i=1;i<=n;i++){
int len; cin>>len;
for(int j=1;j<=len;j++){
int x; cin>>x;
ve[i].push_back(x);
}
}
for(int i=0;i<M;i++) for(int j=1;j<=N;j++) f[i][j]=-1;
f[0][1]=0;
for(int i=1;i<=100;i++){
for(int x=1;x<=n;x++){ //当前接龙的人是k
int cnt=0; //当前还剩多少个数可以做为结尾
for(int j:ve[x]){
if(cnt>0){ //当前数可以做为结尾
if(f[i][j]==-1) f[i][j]=x;
//原先从没有被更新过,因为当前数可以做为结尾,将其更新为i
else if(f[i][j]!=x) f[i][j]=0;
//之前被更新过,并且不是当前这个人,说明有多人可以
cnt--; //剩下的数减一
}
if(f[i-1][j]!=-1&&f[i-1][j]!=x) cnt=k-1;
//f[i-1][j]!=-1用来判断上一轮是否是j结尾
//f[i-1][j]!=i用来判断上一轮是否是当前这个人
}
}
}
for(int i=1;i<=q;i++){
int r,c; cin>>r>>c;
if(f[r][c]==-1) cout<<0<<endl;
else cout<<1<<endl;
}
for(int i=1;i<=n;i++) ve[i].clear();
}
int main(){
int t; cin>>t; while(t--)
solved();
return 0;
}
这里空空如也







有帮助,赞一个