题目链接:点击打开链接
题目大意:略。
解题思路:全排列 + 限制条件(judge()函数注释)。
AC 代码
using namespace std;
typedef long long ll;
/*
len:记录有多少排名的可能个数
vis:是否使用过该点
num:存储预备的数据
rcd:记录符合题意的数据(从num[]获取)
rs:记录最终符合题意的所有数据(从rcd[]获取)
mk:记录预判信息
*/
int n,m,len,vis[20],mk[20][20],num[20],rcd[20],rs[1000000][20];
// 初始化
void init()
{
len=0;
mem(mk,0);
for(int i=0;i<20;i++) // 预备存储数据,取决于题目是需要存储什么类型的数据
num[i]=i;
mem(vis,0);
mem(rcd,0);
mem(rs,0);
}
// 判断是否符合正确的预判
int judge()
{
// f1:标记预判为1的结果; f2:标记预判为0的结果
int f1=1,f2=1;
for(int i=0;i<m;i++) // 通过记录个数判断是否符合预判为1的限定
{
if(mk[i][mk[i][0]+1]==1&&f1)
{
int j=1;
for(int x=0; j<=mk[i][0]&&x<n; x++)
{
if(mk[i][j]==rcd[x])
j++;
}
if(j<mk[i][0]+1) // +1 因为上面 j 先 ++,再判断
f1=0;
}
else // 通过记录个数判断是否符合预判为0的限定
{
int j=1;
for(int x=0; j<=mk[i][0]&&x<n; x++)
{
if(mk[i][j]==rcd[x])
j++;
}
if(j==mk[i][0]+1) // 同上
f2=0;
}
if(!f1 || !f2)
{
break;
}
}
if(f1&&f2)
return 1;
else
return 0;
}
void dfs(int l)
{
if(l==n&&judge())
{
for(int i=0;i<n;i++) // 记录每一组符合题意的数据
{
rs[len][i]=rcd[i];
}
len++;
return;
}
for(int i=0;i<n;i++)
{
if(!vis[i])
{
vis[i]=1;
rcd[l]=num[i];
dfs(l+1);
vis[i]=0;
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int k=0;k<m;k++)
{
int c; scanf("%d",&c);
mk[k][0]=c; // 记录长度
for(int i=1;i<=c+1;i++) // +1 记录后面预判(1、0)
scanf("%d",&mk[k][i]);
}
dfs(0); // 从第0号球员开始搜
printf("%d\n",len);
for(int i=0;i<len;i++)
{
for(int j=0;j<n;j++)
printf("%d ",rs[i][j]);
puts("");
}
}
return 0;
}