您的位置:首页 > 其它

UASCO 1.3 wormholes

2016-10-30 09:01 330 查看
解题思路

通过回溯求出所有组合,然后枚举每个入口进入后是否进入死循环;

解题步骤

1. 将虫洞排序(先按y坐标排, y坐标相同相同再排x坐标);

bool cmp(map c,map v)
{
if(c.y==v.y)
return c.x<v.x;
return c.y<v.y;
}


2.记录每个点t沿x轴方向右边最近的点,保存在next[t]中,若右边没有点,则next[t]=0(由于这里排过序了,所以可以线性查找);

for( int  i=1 ; i<n ; i++ )
{
if(p[i].y<p[i+1].y;
next[i]=i+1;
}


3.回溯,求出n个数两两配对的所有组合,用数组a存,单双成对;

考虑到不能重复(比如12 34和12 43和34 12)这里的限制条件是:偶数位cs一定大于他的前一位cs-1,奇数位一定大于他的前面第二位cs-2;

cs>n时得到一组解

void hs(int cs)
{
if(cs>n)
{
for(int i=1;i<n;i+=2)
{
partner[a[i]]=a[i+1];
partner[a[i+1]]=a[i];
}
sum+=pd();
return;
}
if(cs%2!=0)
{
if(cs>1)
{
for(int i=a[cs-2];i<=n;i++)
{
if(book[i]==0)
{
book[i]=1;
a[cs]=i;
hs(cs+1);
book[i]=0;
}
}
return;
}
for(int i=1;i<=n;i++)
{
if(book[i]==0)
{
book[i]=1;
a[cs]=i;
hs(cs+1);
book[i]=0;
}
}
return ;
}
if(cs%2==0)
{
for(int i=a[cs-1]+1;i<=n;i++)
{
if(book[i]==0)
{
book[i]=1;
a[cs]=i;
}ok[i]=0;

}
}
return;


4.每得到一组解,进行判断:从每个点进去,模拟运动情况,判断是否会进入死循环;

int pd()
{
int flag=0;
for(int i=1;i<=n;i++)
{
memset(book2,0,sizeof(book2));
flag=enter(i);
if(flag==1)return 1;
}
return 0;
}


5.模拟从每个点进去的结果,不会循环返回0,会循环返回1;

int enter(int po)
{
int t=po;
int now=1;
while(1)
{
if(now==1)
{
book2[t]=1;

t=partner[t];
now=0;
}
if(now==0)
{
if(next[t]==0)
return 0;
t=next[t];
if(book2[t]==1)
return 1;
book2[t]=1;
now=1;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  USACO 回溯 暴力枚举