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. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  2. taotao订单系统

    taotao订单系统需求分析.注意点.代码 需要注意的地方: 1.下订单功能一定要使用关系型数据库,因为其设计到钱,而noSql数据库相比来说丢失数据的风险更大. 但是查看订单列表.查看订单详情等功能 ...

  3. Mysql History list length 值太大引起的问题

    1. 环境 Mysql 主从 Mysql版本:5.1.49-log 系统:Red Hat Enterprise Linux Server release 5.4  64bit 2. 表面现象 数据库操 ...

  4. HDU 5655 四边形判断

    CA Loves Stick Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) ...

  5. POJ 1320 Street Numbers 解佩尔方程

    传送门 Street Numbers Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2529   Accepted: 140 ...

  6. 按小时或天切割Nginx日志

    #按小时或天切割Nginx日志到备份文件夹 LOGS_PATH=/home/www/logs/thc SAVE_PATH=/home/www/logs/thc YESTERDAY=$(date -d ...

  7. Idea导入的工程看不到src等代码

    问题描述: 从其他地方拷贝过来的工程,在本地导入到idea中时,展示如下的页面,里面的其他文件都看不到. 解决办法:(不知道是具体的什么原因引起的) 1. 关闭IDEA, 2.然后删除项目文件夹下的. ...

  8. [object-c 2.0 程序设计]object-c file handle (二)

    // // main.m // cmdTry // // Created by Calos Chen on 2017/8/21. // Copyright © 2017年 Calos Chen. Al ...

  9. python—用for循环、while循环和一句话打印九九乘法表

    用for循环打印九九乘法表: for i in range (1,10): for j in range(1,10): print(j,"x",i,"=",i* ...

  10. zhudongfangyu.exe进程是360主动防御进程,用来监控电脑系统,防止电脑病毒出现并阻止病毒或木马的安全进程

    zhudongfangyu.exe进程是360主动防御进程,用来监控电脑系统,防止电脑病毒出现并阻止病毒或木马的安全进程