2017-05-25
题目
输入N表示有N个虫洞,然后N组数据表示虫洞的坐标。有一只奶牛可以也仅可以向x轴正方向移动,所以当虫洞满足一定条件时,它从某个点出发就可能陷入无限循环中。你需要考虑到虫洞的每一种两两配对情况,并且计算出在多少种情况下这只奶牛可能陷入无限循环。
样例
4
0 0
1 0
0 1
1 1
此时有两种情况(0,0)-(1,0),(0,1)-(1,1)是一种 ,(0,0)-(1,1),(0,1)-(1,0)是第二种,而还有一种(0,0)-(0,1),(1,0)-(1,1)则不会陷入循环中。
题解
> 第一个问题是配对,如何保证不重不漏地将虫洞两两配对,我采用了递归的方法。首先定义一个结构体数组,每个结构体表示一个门,里面有一个num变量用于匹配,初始为0,匹配时令其等于另一个num==0的门的序号,并同时将另外那个门的num等于该门的序号,然后进行下一次匹配。
门的序号并非输入时的顺序,而是用了sort函数对这个结构体数组按先行后列的顺序排序。排序方法是自己写一个排序方法的函数作为sort函数的参数,这样可以直接由结构体内的x,y变量进行整个结构体的排序,详情见代码。同时这样的排序也会在下面模拟奶牛行进时起到作用。
匹配结束后(设置一个参数表示已匹配的个数),开始模拟奶牛行进的过程。我将进门出门放在一个函数里,用一个参数表示所进/出的门,另一个表示进还是出,进门则搜寻某门的Num值等于此门的序号,出门则进入下一个序号的门(如果y变量相同的话),这里显现出了排序的另一个作用,判断y变量相同直接进入下一个门即可。
下一个问题是如何判断循环。我想的是如果进入一个已经进过的门,或是由一个已经出过的门再次走出,则可以判定是进入了循环,所以在进出门操作前判断此门是否进出过即可。由每个门进入开始,模拟完毕返回是否循环。
代码
/*
ID: xcwhkh1
LANG: C++
TASK: wormhole
*/
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int x,y;
int num;//匹配用
int in;
int out;
}door [14];
bool st(node a,node b)//用于sort
{
if(a.y<b.y)//先排纵坐标,行相同则排横坐标
return true;
if(a.y==b.y)
if(a.x<b.x)
return true;
return false;
}
int n,sum=0;
int go(int i,int io)//传送、行进都算作一次go,io表示进出门
{
if(io==0)//出
{
if(door[i].out==1)
return 1;
door[i].out=1;//如果已经从该门出去过则循环
for(int j=i+1;j<=n;j++)
if(door[j].y==door[i].y)
return (go(j,1));//找到该行下一个门进入
return 0;//此门后无门,出循环
}
else//进
{
if(door[i].in==1)
return 1;
door[i].in=1;//如果进入过该门则循环
for(int j=1;j<=n;j++)
if(i==door[j].num)
return (go(j,0));//找配对的门
}
return 0;
}
void npair(int temp)//递归匹配虫洞
{
if(temp==n)
{
for(int i=1;i<=n;i++)
{
for(int f=1;f<=n;f++)
{
door[f].in=0;
door[f].out=0;
}
if(go(i,1))//go即为走的过程,返回1表示循环
{
sum++;
break;
}
}
return;
}
if(door[temp].num==0)
{
for(int i=temp+1;i<=n;i++)
if(door[i].num==0)
{
door[i].num=temp;//故下标不能从0开始
door[temp].num=i;
npair(temp+1);
door[i].num=0;//回到未配对的情况
door[temp].num=0;
}
}
else
npair(temp+1);
return ;
}
int main () {
FILE *fin=fopen("wormhole.in","r");
FILE *fout=fopen("wormhole.out","w");
int i,j;
fscanf(fin,"%d",&n);
for(i=1;i<=n;i++)
{
fscanf(fin,"%d%d",&door[i].x,&door[i].y);
door[i].in=0;
door[i].out=0;
}
sort(&door[1],&door[n+1],st);
npair(1);
fprintf(fout,"%d\n",sum);
return 0;
}