有个数据能在我机子上跑对,在服务器上过不去,卡了我很久。后来才发现,有个数组大小少开了一个。
题意是,有头牛只会沿着x轴正方向走,但是y坐标随机。图上有很多虫洞,两两相连,从一个虫洞进去,从对应虫洞出来之后,牛还是会沿着x轴正方向走,让你统计虫洞两两相连的方式,其中会导致牛陷入循环的个数。
关于排列组合,两两相配的个数什么的还好,但是如何生成配对,编程什么的一开始我还真不会。以前也就自己写过全排列或者组合而已,没有写过这种。
/*
ID: modengd1
PROG: wormhole
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
int x[13],y[13];
int rightIndex[13];
int paired[13];
int N;
bool cycle_exists()
{
bool vis[13];
//枚举从不同的点的左边进入
for(int start=1;start<=N;start++)
{
int now=start;
memset(vis,false,sizeof(vis));
vis[now]=true;
while(true)
{
//出
now=paired[now];
if(rightIndex[now]==0)
break;
//检查要进的口是否进过了
if(vis[rightIndex[now]])
return true;
//从右面临近的虫洞进去
now=rightIndex[now];
vis[now]=true;
}
}
return false;
}
int slove()
{
int a=-1,ans=0;
for(int i=1;i<=N;i++)
{
if(paired[i]==0)
{
a=i;
break;
}
}
if(a==-1)
{
if(cycle_exists())
return 1;
else
return 0;
}
for(int i=a+1;i<=N;i++)
{
if(paired[i]==0)
{
paired[i]=a;
paired[a]=i;
ans+=slove();
paired[i]=paired[a]=0;
}
}
return ans;
}
int main()
{
freopen("wormhole.in","r",stdin);
freopen("wormhole.out","w",stdout);
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
scanf("%d%d",&x[i],&y[i]);
}
memset(paired,0,sizeof(paired));
memset(rightIndex,0,sizeof(rightIndex));
//找到各个节点最近的右相邻
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if(y[i]==y[j]&&x[i]<x[j])
{
if(rightIndex[i]==0||x[j]<x[rightIndex[i]])
rightIndex[i]=j;
}
}
}
cout<<slove()<<endl;
return 0;
}