题目链接:点击打开链接
题目大意:略。
解题思路:全排列 + 限制条件(judge()函数注释)。
AC 代码
#include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof a); 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; }