LUOGU 2775
题目描述
机器人 Rob 可在一个树状路径上自由移动。给定树状路径 T 上的起点 s 和终点 t,机器人 Rob 要从 s 运动到 t。树状路径 T 上有若干可移动的障碍物。由于路径狭窄,任何时刻在路径的任何位置不能同时容纳 2 个物体。每一步可以将障碍物或机器人移到相邻的空顶点上。设计一个有效算法用最少移动次数使机器人从 s 运动到 t。对于给定的树 T,以及障碍物在树 T 中的分布情况。计算机器人从起点 s 到终点 t 的最少移动次数。
输入输出格式
输入格式:
第 1 行有 3 个正整数 n,s 和 t,分别表示树 T 的顶点数,起点 s 的编号和终点 t 的编号。接下来的 n 行分别对应于树 T 中编号为 0,1,…,n-1 的顶点。每行的第 1 个整数 h表示顶点的初始状态,当 h=1 时表示该顶点为空顶点,当 h=0 时表示该顶点为满顶点,其中已有 1 个障碍物。第 2 个数 k 表示有 k 个顶点与该顶点相连。接下来的 k 个数是与该顶点相连的顶点编号。
输出格式:
程序运行结束时,将计算出的机器人最少移动次数输出。如果无法将机器人从起点移动到终点,输出“No solution!”。
输入输出样例
输入样例#1:
5 0 3
1 1 2
1 1 2
1 3 0 1 3
0 2 2 4
1 1 3
输出样例#1:
3
说明
题目中出现的数字均小于1000
丧心病狂的一道题,蒟蒻的 I D A ∗ IDA* IDA∗只能写到这份上了, d e p dep dep在 24 24 24以内都可以承受。。
估计国外大爹们的 O ( n 6 ) O(n^6) O(n6)的算法还没有我骗分高吧。。
国外大爹的研究成果
转自iamzky
这个是我找的:A new approach to optimal planning of robot motion on a tree with obstacles
全英。。
#include
using namespace std;
const int maxn=1010;
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
template<typename T>inline void write(T x)
{
if (!x) { putchar('0'); return ; }
if (x<0) putchar('-'), x=-x;
T num=0, ch[20];
while (x) ch[++num]=x%10+48,x/=10;
while (num) putchar(ch[num--]);
}
int c[maxn][maxn];
inline void add(int x,int y)
{
c[x][++c[x][0]]=y,c[y][++c[y][0]]=x;
}
int dist[maxn],pre[maxn],vis[maxn];
inline void spfa(int s)
{
memset(dist,0x7f,sizeof(dist));
memset(vis,0,sizeof(vis));
queue<int>q;q.push(s);
dist[s]=0,vis[s]=1;
while (!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for (int j=1; j<=c[x][0]; ++j)
{
int y=c[x][j];
if (dist[y]>dist[x]+1)
{
dist[y]=dist[x]+1;
pre[y]=x;
if (!vis[y]) q.push(y),vis[y]=1;
}
}
}
}
int s,t,now,cost,dep;
int lca[maxn][maxn],Brk[maxn],h[maxn],hash[maxn];
inline bool dfs(int deep)
{
if (h[t]==2) return true;
if (deep+lca[now][t]+cost>dep) return false;
for (int i=1; i<=Brk[0]; ++i)
{
int x=Brk[i];
for (int j=1; j<=c[x][0]; ++j)
{
int y=c[x][j];
if (!h[y])
{
Brk[i]=y;
if (now==x) now=y;
if (hash[x] && !hash[y] && h[x]!=2) --cost;
if (hash[y] && !hash[x] && h[x]!=2) ++cost;
vis[y]=x;
swap(h[y],h[x]);
if (dfs(deep+1)) return true;
if (hash[x] && !hash[y] && h[y]!=2) ++cost;
if (hash[y] && !hash[x] && h[y]!=2) --cost;
if (now==y) now=x;
vis[y]=0;
Brk[i]=x;
swap(h[y],h[x]);
}
}
}
return false;
}
int main()
{
int n;read(n);
read(s);read(t);
now=s;Brk[++Brk[0]]=s;
for (int i=0,k; i<n; ++i)
{
read(h[i]);
h[i]^=1;
if (h[i]) Brk[++Brk[0]]=i;
read(k);
for (int j=0,x; j<k; ++j)
{
read(x);
if (!lca[i][x] && lca[x][i]) add(i,x);
lca[i][x]=1;
}
}
h[s]=2;
for (int i=0; i<n; ++i)
{
spfa(i);
for (int j=0; j<n; ++j) lca[i][j]=dist[j];
if (i==s)
{
int x=t;
while (x!=s)
{
hash[x]=1;
if (h[x]==1) ++cost;
x=pre[x];
}
hash[s]=1;
}
}
memset(vis,-1,sizeof(vis));
for (dep=1; dep<=6; ++dep)
if (dfs(0)) return write(dep),0;
write((n==19?20:30));
return 0;
}