3205: [Apio2013]机器人

Time Limit: 15 Sec  Memory Limit: 128 MB
Submit: 1007  Solved: 240
[Submit][Status][Discuss]

Description

VRI(Voltron
机器人学会)的工程师建造了 n个机器人。任意两个兼容的机器人站在同一个格子时可以合并为一个复合机器人。我们把机器人用 1至 n编号(n ≤
9)。如果两个机器人的编号是连续的,那么它们是兼容的,可以合并成一个复合机器人。最初这   n  
个机器人各自都只有唯一的编号。而一个由两个或以上的机器人合并构成的复合机器人拥有两个编号,分别是构成它的所有机器人中最小和最大的编号。例如,
2号机器人只可以与 1号或 3号机器人合并。若 2号机器人与 3号机器人合并,可构成编号为 2-3的复合机器人。如果编号为
2-3的复合机器人与编号为 4-6的复合机器人合并,可构成编号为 2-6的复合机器人。当所有机器人合并以后则构成 1-n复合机器人。工程师把这
n个机器人放在了一个封闭的房间中,房间四周均是墙。该房间被划分成 w     h   
个方格。有些方格有障碍物,机器人不可经过或停留;其余方格允许多个机器人停留,同时允许机器人经过。任何时候一个机器人只占用一个方格。初始时刻,所有
机器人均在不同的方格中。这些原始的机器人不会自发地移动。它们只有被工程师沿   x轴或
y轴推动后,才会沿推动的方向不断向前直线移动,直至碰到障碍物或墙停止移动。停止移动后,它会扫描当前的格子是否存在可以与它合并的机器人,如果有,则
合并并继续检查,直至不能再合并为止。工程师只能沿水平向左、水平向右、竖直向上、竖直向下四个方向推动机器人,并且,在机器人尚未停止移动时,不允许推
动其它机器人,因此任何时刻,房间中都只能有一个机器人移动,为了帮助机器人转向,工程师在一些格子中放置了转向器。具体地说,转向器分为顺时针转向器
(右转器)和逆时针转向器(左转器),顺时针转向器可以使到达该格子的机器人沿顺时针方向转向  
90_;逆时针转向器可以使到达该格子的机器人沿逆时针方向转向
90_。现在,我们将告诉你初始时刻房间内的信息。请你计算工程师最少共计需要推动机器人多少次,才能把所有的 n个机器人全部合并(如果可能的话)。

Input

你的程序必须从标准输入读入。输入的第 1行包含 3个整数 n、w和 h,用空格隔开。输入文件中接下来的 h行描述初始时刻房间内的信息,每行包含w个字符。这w* h 字符中每一个表示房间中的一个格子,意义如下:
 
‘ 1’至‘9’:表示该方格中有一个机器人,编号为这个数字;
‘ x’:表示该方格有障碍物;
 
‘ A’:表示该方格中有一个逆时针转向器;
 
‘ C’:表示该方格中有一个顺时针转向器;
‘ .’:表示该方格为空地。

Output

你的程序必须输出到标准输出。输出仅一个整数,表示最少需要推动的次数。
若不能使所有机器人全部合并,输出-1。

Sample Input

4 10 5
1.........
AA...x4...
..A..x....
2....x....
..C.3.A...

Sample Output

5

HINT

第一步:向右推动 3 号机器人,当它碰到转向器后会向上继续移动,直至碰到墙壁停止移动。第二步:向上推动 4
号机器人,当它碰到墙壁后停止移动,与3 号机器人合并,构成  3-4 号机器人 第三步:向上推动 2
号机器人,当它碰到转向器后会向左移动,由于左侧为墙壁,故停留在原地。第四步:向右推动  2
号机器人,由于它在一个转向器上,故它会向上移动,直至碰到墙壁停止移动,与  1 号机器人合并,构成 1-2 号机器人。第五步:向左推动  3-4
号机器人,当它碰到墙壁后停止移动,与 1-2 号机器人合并,构成  1-4 号机器人。

n ≤ 9,w ≤ 500且   h ≤ 500

Source

[Submit][Status][Discuss]

都说是比较明显的斯坦纳树,但我并没有看出来,只是状态转移比较像而已,和连通性并没有什么关系(或许是合并的过程比较像最小生成树)。

http://wyfcyx.is-programmer.com/posts/75949.html

不好写,卡空间又卡时间。注意能用栈的不要用队列,栈的常数小不少。

不知道为什么按照lych的代码写的,改得几乎一样了,常数还要大一半。

还有那些用std::queue过的真心服气。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=,M=N*N+,inf=0x3f3f3f3f;
const int dx[]={-,,,},dy[]={,,,-};
char ch;
struct P{ int x,y; }go[N][N][],q1[M],q2[M],pos[N];
int n,m,s,ans,tim,a[N][N],f[][][N][N],inq[N][N],vis[N][N][],c[M],val[M]; int add(int x){ x++; return (x>=M) ? x-M : x; }
void inc(int &x){ x=add(x); }
bool jud(int x,int y){ return x>= && x<=n && y>= && y<=m && a[x][y]!=; } P dfs(int x,int y,int d){
if (vis[x][y][d]==tim) return (P){-,-};
if (go[x][y][d].x || go[x][y][d].y) return go[x][y][d];
vis[x][y][d]=tim; int t=d;
if (a[x][y]==) t=(t+)%;
if (a[x][y]==) t=(t+)%;
int xx=x+dx[t],yy=y+dy[t];
if (!jud(xx,yy)) return go[x][y][d]=(P){x,y};
return go[x][y][d]=dfs(xx,yy,t);
} void spfa(int l,int r){
memset(inq,,sizeof(inq)); P ss;
int top=,st=,ed=,mn=inf,mx=-inf;
rep(x,,n) rep(y,,m) if (f[l][r][x][y]!=inf)
q1[++top]=(P){x,y},val[top]=f[l][r][x][y],mn=min(mn,val[top]),mx=max(mx,val[top]); rep(i,,mx) c[i]=;
rep(i,,top) c[val[i]]++;
rep(i,mn+,mx) c[i]+=c[i-];
for (int i=top; i; i--) q2[c[val[i]]--]=q1[i];
rep(i,,top) q1[i]=q2[top-i+]; while (top || st!=ed){
int now=add(st);
if (st==ed || (top && f[l][r][q1[top].x][q1[top].y]<f[l][r][q2[now].x][q2[now].y])) ss=q1[top--]; else ss=q2[st=now];
int x=ss.x,y=ss.y; inq[x][y]=;
rep(d,,){
P pp=go[x][y][d];
if (pp.x==x && pp.y==y) continue;
if (~pp.x && f[l][r][pp.x][pp.y]>f[l][r][x][y]+){
f[l][r][pp.x][pp.y]=f[l][r][x][y]+;
if (!inq[pp.x][pp.y]) inq[pp.x][pp.y]=,inc(ed),q2[ed]=pp;
}
}
}
} int main(){
freopen("bzoj3205.in","r",stdin);
freopen("bzoj3205.out","w",stdout);
scanf("%d%d%d",&s,&m,&n); ans=inf;
memset(f,0x3f,sizeof(f));
rep(i,,n) rep(j,,m){
scanf(" %c",&ch);
if (ch>='' && ch<=''){
int t=ch-'';
a[i][j]=t; pos[ch-'']=(P){i,j}; f[t][t][i][j]=;
}
if (ch=='A') a[i][j]=;
if (ch=='C') a[i][j]=;
if (ch=='x') a[i][j]=;
}
rep(i,,n) rep(j,,m) if (a[i][j]!=) rep(k,,) if (a[i][j]!=) tim++,go[i][j][k]=dfs(i,j,k);
rep(i,,s) f[i][i][pos[i].x][pos[i].y]=;
rep(l,,s) rep(i,,s-l+){
int j=i+l-;
rep(k,i,j-) rep(x,,n) rep(y,,m)
f[i][j][x][y]=min(f[i][j][x][y],f[i][k][x][y]+f[k+][j][x][y]);
spfa(i,j);
}
rep(x,,n) rep(y,,m) ans=min(ans,f[][s][x][y]);
printf("%d\n",(ans<inf)?ans:-);
return ;
}

[BZOJ3205][APIO2013]Robot(斯坦纳树)的更多相关文章

  1. [APIO2013]机器人(斯坦纳树)

    题目描述 VRI(Voltron 机器人学会)的工程师建造了 n 个机器人.任意两个兼容的机 器人站在同一个格子时可以合并为一个复合机器人. 我们把机器人用 1 至 n 编号(n ≤ 9).如果两个机 ...

  2. BZOJ 3205 [Apio2013]机器人 ——斯坦纳树

    腊鸡题目,实在卡不过去. (改了一下午) 就是裸的斯坦纳树的题目,一方面合并子集,另一方面SPFA迭代求解. 优化了许多地方,甚至基数排序都写了. 还是T到死,不打算改了,就这样吧 #include ...

  3. [Bzoj3205][Apio2013]机器人(斯坦纳树)(bfs)

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 977  Solved: 230[Submit][Status] ...

  4. [APIO2013]机器人[搜索、斯坦纳树]

    题意 题目链接 分析 记 g(d,x,y) 表示从 (x,y) 出发,方向为 d 到达的点,这个可以通过记忆化搜索求出,注意如果转移成环(此时向这个方向走没有意义)要特判. 记 f(l,r,x,y) ...

  5. bzoj 3205: [Apio2013]机器人【dfs+斯坦纳树+spfa】

    第一次听说斯坦纳树这种东西 先dfs预处理出来dis[i][j][k]表示格子(i,j)向k方向转移能到哪,记忆话搜索预处理,注意如果有环的话特判一下 设f[i][j][x][y]表示复合机器人i-j ...

  6. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  7. HDU 4085 斯坦纳树

    题目大意: 给定无向图,让前k个点都能到达后k个点(保护地)中的一个,而且前k个点每个需要占据后k个中的一个,相互不冲突 找到实现这个条件达到的选择边的最小总权值 这里很容易看出,最后选到的边不保证整 ...

  8. hdu4085 Peach Blossom Spring 斯坦纳树,状态dp

    (1)集合中元素表示(1<<i), i从0开始 (2)注意dp[i][ss] = min(dp[i][ss], dp[i][rr | s[i]] + dp[i][(ss ^ rr) | s ...

  9. hdu 3311 斯坦纳树

    思路:虚拟一个0号节点,将每个点建一条到0号节点的边,权值为挖井需要的价值.并要保证0号节点同另外n个寺庙一样被选择即可. 然后就是求斯坦纳树了. #include<map> #inclu ...

随机推荐

  1. 阿里巴巴前端面试parseInt()函数的面试题

    JavaScript 是弱类型语言,为了保证数值的有效性,在处理数值的时候,我们可以对数值字符串进行强行转换.如 parseInt 取整和 parseFloat 取浮点数.Java 也有 Intege ...

  2. Java多线程-一个简单的线程,实现挂起和恢复的功能

    public class MySprite implements Runnable { /* * 线程用变量 */ private boolean running = false; private b ...

  3. fs.watch 爬坑

    上星期用 fs.watch 和 readline.createInterface 对pm2的合并日志做了监控,根据指定的错误信息重启服务 发现不管是手动vim编辑日志,还是等待日志自动输出. fs.w ...

  4. IDEA新建时选项没有java class问题

    解决办法: 点击你的project F4打开project stucture 点击左边的module 点击右边的source后添加src就可以了  添加的src就是源码可以放置的地址

  5. bzoj 1050: [HAOI2006]旅行comf&&【codevs1001】

    Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最 ...

  6. 【CF1027D】Mouse Hunt(拓扑排序,环)

    题意:给定n个房间,有一只老鼠可能从其中的任意一个出现, 在第i个房间设置捕鼠夹的代价是a[i],若老鼠当前在i号房间则下一秒会移动到b[i]号, 问一定能抓住老鼠的最小的总代价 n<=2e5, ...

  7. JS高级技巧(简洁版)

    高级函数 由于在JS中,所有的函数都是对象,所以使用函数指针十分简单,也是这些东西使JS函数有趣且强大 安全的类型检测 JS内置的类型检测机制并不是完全可靠的 typeof 操作符返回一个字符串,表示 ...

  8. 【洛谷 P3469】[POI2008]BLO-Blockade(割点)

    题目链接 题意:一个无向联通图,求删去每个点及其所有边后有多少有序点对的连通性发生了变化. Tarjan求割点的例题.. 如果当前点不是割点,那么它对整个图的连通性不产生影响,只有自己与其他\(n-1 ...

  9. Chrome浏览器跨域插件

    Moesif Origin & CORS Changer 这个插件允许发送跨域请求,重写Request Origin 和 CORS headers. 解决Debug Javascript时候出 ...

  10. MS笔试中的一个关于函数返回的“小”题

    Which of following C++ code is correct ? A. int f() { ); return *a; } B. int *f() { int a[3] = {1,2, ...