题解
目前为止最难的题,有多种做法,这里给出一个比较好理解的方法—配对法
大体思路是深度递归创造所有的配对b[],然后对每个配对检验是否有回路。
代码
/*
PROG:wormhole
ID:imking022
LANG:C++
*/
#include <iostream>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
int n,ans;
typedef struct node{
int x,y;
} P;
P a[14];
int b[14];
int doit(int num, int x, int begin, int into){ //
// num 运行次数, x 当前位置, begin 开始位置, into 进1 出0
if( num!=1 && x == begin && into == 0) return 1; // 当走了不止一次
// 又回到起点并且是出时,则有回路
if( into == 0){ // 是出时
if( a[x].y == a[x+1].y ) return doit(num+1,x+1 ,begin,1);// 可以向后走
else return 0;// 否则无环
}
if( into == 1) return doit(num+1, b[x] , begin, 0);// 是进时,走入虫洞 会从b[x]出
}
bool check(){ // 遍历配对,检测回路
for(int j =1 ; j<=n; j++){
if( doit(1,j,j,0) == 1 )
return true;
}
return false;
};
void dfs(int x){// 深度递归 实现配对
if( x>n ){
if( check()){
ans++;
return;
}
}
if( b[x] == 0 ){
for( int i = x+1; i<= n; i++){
if( b[i] == 0 ){
b[x] = i;b[i] = x;
dfs(x+1);
b[x] = 0;b[i] = 0;
}
}
} else{
dfs(x+1);
}
}
int main(void){
cin>>n;
ans = 0;
for(int i=1;i<=n;i++){
cin>>a[i].x >> a[i].y;
}
sort(a+1,a+n+1,[](P a, P b){// 关键要排序
return a.y == b.y ? a.x < b.x : a.y<b.y;
});
dfs(1);
cout<<ans<<endl;
return 0;
}