题目大意
农夫约翰爱好在周末进行高能物理实验的结果却适得其反,导致农场上产生了N个虫洞(2<=N<=12,n是偶数),每个在农场二维地图的一个不同点。
根据他的计算,约翰知道他的虫洞将形成 N/2 连接配对。例如,如果A和B的虫洞连接成一对,进入虫洞A的任何对象体将从虫洞B出去,朝着同一个方向,而且进入虫洞B的任何对象将同样从虫洞A出去,朝着相同的方向前进。这可能发生相当令人不快的后果。
例如,假设有两个成对的虫洞A(1,1) 和 B(3,1),贝茜从(2,1)开始朝着 +x 方向(右)的位置移动。贝茜将进入虫洞 B(在(3,1)),从A出去(在(1,1)),然后再次进入B,困在一个无限循环中!
| . . . .
| A > B . 贝茜会穿过B,A,
+ . . . . 然后再次穿过B
农夫约翰知道他的农场里每个虫洞的确切位置。虽然他不记得贝茜的当前位置,但是他知道贝茜总是向着 +x 的方向走。请帮助农夫约翰计算不同的虫洞配对(情况),使贝茜可能从不幸的位置开始被困在一个无限循环中。
输入格式
第1行:N,虫洞的数目
第2到N+1行:每一行都包含两个空格分隔的整数,描述一个以(x,y)为坐标的单一的虫洞。每个坐标是在范围 0..1000000000。
输出格式
一个数字:会使贝茜从某个起始点出发沿+x方向移动卡在循环中的不同的配对。
样例输入
4
0 0
1 0
1 1
0 1
样例输出
2
题解
分为两步,第一步找出所有配对的方式,不能重复,更不能遗漏。显然不会是个全排列,因为每对的顺序无所谓,对于对之间的顺序也无所谓。本处的做法是,人为规定一个顺序,这样便不用考虑去重的问题:每对由两个元素构成,每对的第一个元素永远挑没有被挑走的第一个;每对的第二个元素依此向后挑(每对内均是小的在前大的在后,且每对与每对之间,每对的第一个元素是升序排列的)。过程如下:
6个元素,分成三组,元素依此为1 2 3 4 5 6;
以下是算法流程:
1 2 ,3 4 ,5 6
1 2 ,3 5 ,4 6
1 2 ,3 6 ,4 5
1 3 ,2 4 ,5 6
1 3 ,2 5 ,4 6
1 3 ,2 6 ,4 5
1 4 ,2 3 ,5 6
1 4 ,2 5 ,3 6
1 4 ,2 6 ,3 5
。
。
。
第二个问题是对于每种配对方式,怎样判断牛进入了无限循环:用step表示牛经过的虫洞个数,由于牛永远向一个方向走,所以牛走的路径是唯一的,如果牛第二次进入(不是经过,因为经过可能是离开)同一个虫洞,那么一定会陷入循环,所以当step>2*N的时候,一定陷入循环。
代码
#include<stdio.h>
int N,count=0,flag=0;
long int a[15][2];
int b[15][2];
int g(int step,int i)
{
int number,j,s;
number=b[i][1];
if(step>2*N)
{flag=1;return 0;}
else
{
for(j=0;j<N;j++)
{
if(number==b[j][1]&&j!=i)
{ s=j;break;}
}
for(j=0;j<N;j++)
{
if(a[j][1]==a[s][1]&&a[j][0]>a[s][0])
{
g(step+1,j);
break;
}
}
}
return 0;
}
int f(int k)
{
int i,j;
if(k==0)
{
for(i=0;i<N;i++)
{
flag=0;
g(0,i);
if(flag==1)
break;
}
if(flag==1)
count++;
}
else
{
for(j=0;j<N;j++)
{
if(b[j][1]==0)
{
b[j][1]=k/2;
break;
}
}
for(i=0;i<N;i++)
{
if(b[i][1]!=0)
continue;
else
{
b[i][1]=k/2;
f(k-2);
b[i][1]=0;
}
}
b[j][1]=0;
}
return 0;
}
int main()
{
scanf("%d",&N);
int i,j,temp;
for(i=0;i<N;i++)
{
b[i][0]=i;
b[i][1]=0;
}
// b[0][1]=1;b[1][1]=1;
for(i=0;i<N;i++)
scanf("%d %d",&a[i][0],&a[i][1]);
for(i=0;i<N;i++)
for(j=0;j<N-1-i;j++)
{
if(a[j][1]>a[j+1][1])
{
temp=a[j][1];
a[j][1]=a[j+1][1];
a[j+1][1]=temp;
temp=a[j][0];
a[j][0]=a[j+1][0];
a[j+1][0]=temp;
}
}
for(i=0;i<N;i++)
for(j=0;j<N-1-i;j++)
{
if(a[j][1]==a[j+1][1])
if(a[j][0]>a[j+1][0])
{
temp=a[j][1];
a[j][1]=a[j+1][1];
a[j+1][1]=temp;
temp=a[j][0];
a[j][0]=a[j+1][0];
a[j+1][0]=temp;
}
}
f(N);
// g(0,1);
printf("%d\n",count);
for(i=0;i<N;i++)
printf("%d %d\n",a[i][0],a[i][1]);
return 0;
}