额,这道题是五校联考2day2的第2题
一开始还真是看不懂。
原题目描述得又臭又长,又繁琐,又难懂。(这出题人是个吹水的好苗子啊。。。囧。。。真会坑人)读了半天,才明白了题目的大意是这样的:
Description:
有 n 个互相追逐的点 ( 1≤n≤20000 ),每个点 i 都有它自己的目标点 A[i](注意 A[i] 为给出的 n 个点中的一个)。已知每个点的初始坐标,开始计时后,每单位时间它们会向各自的目标点移动 1 单位距离。
当点 i 距离它的目标点只有 1 单位距离、或者它与目标点的距离在 1 单位时间内保持不变时,它会跟随它的目标点向同一方向移动(即它的移动方向由它的目标点决定)。我们称一个点“不知道自己的移动方向”当且仅当它的移动方向由它自己决定(注意如果一个点的移动方向决定于一个“不知道自己的移动方向”的点的移动方向,那么它不能算是“不知道自己的移动方向”)。一个“不知道自己的移动方向”的点会停下不动。
现在询问的是:在过了无限长的时间后,任意一组“不知道各自的移动方向”的点。输出任意一组且不要求输出顺序。
真是无语了。。。题目那么长,其实做起来却很简单——就是要我们求环!!因为如果一个点追着目标点,一直在追的话,有无限长的时间,那么他们就一定会慢慢聚拢在一起,最终停下,达成目标状态。那么这就很明显地看出了这分明就是要我们找环吗!
我们可以输入的每个点向他的目标点连条边,并通过搜索找出第一次出现环的情况。
并用数组存下想对应的状态,最后输出找到的状态就行了。(友情提示:递归会爆栈,要改成while循环或更优的找法。。更优的方法是什么我就不多说了,要是觉得好奇,可以自己想想)
代码程序实现起来很简单
For example:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#define N 200008
#define fo(i,a,b) for (int i=a;i<=b;i++)
using namespace std;
int n,a[N],b[N],c[N],wz[N][3],tot=0;
int Find_Huan(int x)
{
while (!b[x])
{
b[x]=++tot;
c[tot]=x;
x=a[x];
}
return x;
}
int main()
{
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
fo(i,1,n) scanf("%d%d",&wz[i][1],&wz[i][2]);
int x=Find_Huan(1);
printf("%d\n",tot-b[x]+1);
fo(i,b[x],tot) printf("%d ",c[i]);
return 0;
}
这道题告诉我们,有时候题目很繁琐的时候,我们要学会整理条件,并找出有用的条件,筛掉无用的条件,让自己思路更清晰。
遇到这种看似难题的时候,不能轻易放弃,要坚持想方法,要相信就算是水法,也一定可以骗分的。说不准你的水法就是这道题的正解呢!