USACO-Section 1.3 Wormholes[搜索]

来源:互联网 发布:林州豫广网络客服电话 编辑:程序博客网 时间:2024/05/29 19:22

题意:
农夫约翰爱好在周末进行高能物理实验的结果却适得其反,导致农场上产生了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

题解:
深度搜索 找到所有两两配对的组合;
因为出了虫洞只能向右走,所以每次出洞其右侧必须还有虫洞,达到n次移动则是死循环。

/*ID:jsntrdy1PROG: wormholeLANG: C++*/#include<cstdio>#include<iostream>#include<cstring>#include<fstream>#include<algorithm>using namespace std;ifstream fin("wormhole.in");ofstream fout("wormhole.out");int n;const int N=13;struct node{    int x;    int y;}p[N];int pairs[N];int right_next[N];//各虫洞右边虫洞的编号,如无则为0 bool cmp(node a,node b){    if(a.y!=b.y)      return a.y<b.y;    else      return a.x<b.x;}bool isOK(){     for(int i=1;i<=n;i++)     {        int t=i;        //n个虫洞最多进行n次移动        for(int j=0;j<n;j++)            t=right_next[pairs[t]]; //移动到下一个虫洞的右边,如果右边没有虫洞了,那么t为0         if(t)            return true;     }     return false;    }} int f(){    int i,ans=0;    for(i=1;i<=n;i++){        if(!pairs[i])            break;    }       //如果全部配对进行判断,否则找到一个虫洞        if(i>n){        if(isOK())            return 1;        else         return 0;    }    for(int j=i+1;j<=n;j++){        if(!pairs[j]){            pairs[i]=j;            pairs[j]=i;            ans+=f();//i-j配对,并往下面递归 ,并将方法数加到ans上            pairs[i]=pairs[j]=0; //回溯        }    }    return ans;}int main(){    fin>>n;    for(int i=1;i<=n;i++)      fin>>p[i].x>>p[i].y;    //先按 y 升序,再按 x 升序      sort(p+1,p+1+n,cmp);    for(int i=1;i<n;i++){        if(p[i].y==p[i+1].y){            right_next[i]=i+1;        }    }    fout<<f()<<endl;    return 0;}
原创粉丝点击