[APIO2013]机器人

description

solution

dpl,r,i,j:dp_{l,r,i,j}:dpl,r,i,j​: 在(i,j)(i,j)(i,j)位置合并编号为[l,r][l,r][l,r]区间内的所有机器人的最小花费

toi,j,k:to_{i,j,k}:toi,j,k​: 从(i,j)(i,j)(i,j)以kkk方向推机器人最终停止的位置,用dfs记忆化搜索模拟即可

dpl,r,i,j=min⁡{dpl,k,i,j+dpk+1,r,i,j∣l≤i<r}dp_{l,r,i,j}=\min\{dp_{l,k,i,j}+dp_{k+1,r,i,j}\big| l\le i<r\}dpl,r,i,j​=min{dpl,k,i,j​+dpk+1,r,i,j​∣∣​l≤i<r}

dpl,r,i,j+1→toi,j,kdp_{l,r,i,j}+1\rightarrow to_{i,j,k}dpl,r,i,j​+1→toi,j,k​ 该转移就是一层在(i,j)(i,j)(i,j)位置上的最短路,用类bfsspfa跑即可

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define inf 0x3f3f3f3f
#define LEN 500000
struct node {int x, y;node(){}node( int X, int Y ) {x = X, y = Y;}
}robot[10], to[505][505][4], s[500005], t[500005];
int n, col, row, cnt, top;
char room[505][505];
int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, -1, 0, 1 };
int f[10][10][505][505];
int id[505][505][4];
bool vis[505][505];
int w[1000005], sum[1000005];node dfs( int x, int y, int k ) {if( id[x][y][k] == cnt ) return node( 0, -1 );id[x][y][k] = cnt;if( to[x][y][k].y ) return to[x][y][k];int dir = k;if( room[x][y] == 'C' ) dir = ( dir + 1 ) % 4;if( room[x][y] == 'A' ) dir = ( dir + 3 ) % 4;int tx = x + dx[dir], ty = y + dy[dir];if( tx < 1 || tx > row || ty < 1 || ty > col || room[tx][ty] == 'x' )return to[x][y][k] = node( x, y );elsereturn to[x][y][k] = dfs( tx, ty, dir );
}void spfa( int l, int r ) {memset( sum, 0, sizeof( sum ) );memset( vis, 0, sizeof( vis ) );int minn = inf, maxx = -inf;for( int i = 1;i <= top;i ++ ) {sum[w[i]] ++;minn = min( minn, w[i] );maxx = max( maxx, w[i] );vis[s[i].x][s[i].y] = 1;}//类后缀数组方法对队列中当前层位置进行手动排序编号 for( int i = minn + 1;i <= maxx;i ++ ) sum[i] += sum[i - 1];for( int i = top;i;i -- )t[sum[w[i]] --] = s[i];for( int i = 1;i <= top;i ++ )s[i] = t[top - i + 1];int head = 0, tail = 0, now; node u, v;//%LEN:手动进行空间回收利用 while( top || head != tail ) {now = head % LEN + 1;if( head == tail || ( top && f[l][r][s[top].x][s[top].y] < f[l][r][t[now].x][t[now].y] ) )u = s[top], top --;elsehead = now, u = t[head];vis[u.x][u.y] = 0;for( int i = 0;i < 4;i ++ ) {v = to[u.x][u.y][i]; if( v.x && f[l][r][v.x][v.y] > f[l][r][u.x][u.y] + 1 ) {f[l][r][v.x][v.y] = f[l][r][u.x][u.y] + 1;if( ! vis[v.x][v.y] ) {vis[v.x][v.y] = 1;tail = tail % LEN + 1;t[tail] = v;}}}}
}int main() {memset( f, 0x3f, sizeof( f ) );scanf( "%d %d %d", &n, &col, &row );for( int i = 1;i <= row;i ++ ) {scanf( "%s", room[i] + 1 );for( int j = 1;j <= col;j ++ )if( room[i][j] < '0' || room[i][j] > '9' )continue;else {int k = room[i][j] - '0';robot[k] = node( i, j );f[k][k][i][j] = 0;}}//to(i,j,k):(i,j)位置按k方向推机器人最终停止的位置 for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )if( room[i][j] == 'x' )continue;elsefor( int k = 0;k < 4;k ++ )cnt ++, to[i][j][k] = dfs( i, j, k );for( int i = 1;i <= n;i ++ )s[top = 1] = robot[i], w[1] = 0, spfa( i, i );//f(l,r,i,j,):在(i,j)位置上合并[l,r]编号内的机器人的最小花费 for( int len = 1;len <= n;len ++ )//区间DP 由小到大 for( int l = 1;l <= n;l ++ ) {int r = l + len;if( r > n ) break;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )for( int k = l;k < r;k ++ )f[l][r][i][j] = min( f[l][r][i][j], f[l][k][i][j] + f[k + 1][r][i][j] );top = 0;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )if( f[l][r][i][j] < inf ) //状态本身要存在才能进行下一层转移 s[++ top] = node( i, j ), w[top] = f[l][r][i][j];spfa( l, r );}int ans = inf;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )ans = min( ans, f[1][n][i][j] );printf( "%d\n", ans < inf ? ans : -1 );return 0;
}

[APIO2013]机器人(DP+SPFA最短路)相关推荐

  1. 3205: [Apio2013]机器人

    3205: [Apio2013]机器人 Time Limit: 15 Sec  Memory Limit: 128 MB Submit: 525  Solved: 131 [Submit][Statu ...

  2. bzoj 1003物流运输 区间dp+spfa

    基本思路: 一开始确实没什么思路,因为觉得怎么着都会超时,然后看一下数据范围,呵,怎么都不会超时. 思路: 1.看到能改变线路,想到可以用以下区间dp,区间dp的话,先枚举长度,枚举开始位置,然后枚举 ...

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

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

  4. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge Submit: 1572  Solved:  ...

  5. 【BZOJ3205_洛谷3638】[APIO2013]机器人(动态规划)

    题目: 洛谷3638 分析: 卡了一天的神题--(OrzJumpmelon) 首先预处理出从点\(p\)向\(d\)方向出发最终能到达的点\(nxt[p][d]\).这个可以直接记忆化搜索解决.如果出 ...

  6. BZOJ1003 物流运输(dp+spfa)

    题目: 1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8000 Solved: 3343 [Submit][ ...

  7. ZOJ1027 Travelling Fee(DP+SPFA)

    给一张有向无环图,边都有花费,从某点到某点走的那条路径上的那一条花费最多的边可以省掉,问从起点到终点的最少花费的多少, 往DP想的话,就可以写出这个状态dp[u][mx],表示到达u点已经省掉的花费为 ...

  8. 算法提高课-图论-单源最短路的建图方式-AcWing 1127. 香甜的黄油:spfa最短路

    题目分析 来源:acwing 分析: 多源汇最短路.所以我们首先想到的是floyd算法, 可是它的复杂度是O(n3)O(n^3)O(n3),会超时.所以我们需要另外考虑. 任意一个点作为起点求出到所有 ...

  9. TYVJ P2032 「Poetize9」升降梯上 spfa最短路

    %%%暴搜出奇迹%%%@SiriusRen 其实我刚开始题读错了,才导致我写图论... spfa跑最短路,开一个node记录状态(pair当然滋磁):所在楼层和槽的位置 以层数为1,槽在0的位置 为初 ...

最新文章

  1. python gui编程框架添加工具栏_python gui编程,我是初学者。用tk,制作下拉菜单的command不分我想打开另一个界面。如和解决,求解!!...
  2. WP7应用开发笔记(12) 添加页面动画
  3. JZOJ 4676. 【NOIP2016提高A组模拟7.21】模板串
  4. Pyhon Django 表单类ModelForm注册案例(可直接操作数据库)
  5. java中$和 的区别详解_Mybatis之#{}与${}的区别使用详解
  6. 设计模式(一)六大原则
  7. free mybatis 不生效_Mybatis非空判断没有生效
  8. chinapub matlab,MATLAB 5手册
  9. 计算机中华五岳说课稿,关于说课稿集合6篇
  10. 微信小程序开发之微信小程序交互
  11. 2022年最新版初级商业数字营销师直通车题库
  12. vue 生成qrCode二维码保存图片至本地
  13. (十九)通俗易懂理解——无人驾驶概述
  14. Flutter 弹出键盘报错解决
  15. 信号处理--sinc函数
  16. 2022-2028全球及中国光伏金属化铝膏行业研究及十四五规划分析报告
  17. MySQL数据库中where条件查询(比较运算符查询、逻辑运算符查询、模糊查询、范围查询、空判断查询)
  18. 工作Delay,应该吸取什么教训?(一)
  19. c++primer(第五版) 第十五章 面向对象程序设计习题答案
  20. fenix3 hr 中文说明书_Fenix3HR中英文菜单对照.pdf

热门文章

  1. e2200网卡驱动 linux,Linux驱动修炼之道-驱动中一些常见的宏
  2. JAVA类思维_面向对象思维 Java中的类和对象及其应用
  3. 计算机PS英语词汇,操作计算机必读(必会)的53个英文单词共享
  4. sql 计算 某字段 不同值出现 的次数_教你如何合理选用和计算电线规格,电线回路分配和注意事项...
  5. linux代码段起始地址设置,Arch Linux安装后的一些初始设置简介
  6. java struts 文件下载_Struts2文件下载实例
  7. 访问Web服务器时 使用的协议是,使用SOAP协议访问Web服务
  8. charts漏斗图表_ECharts漏斗图属性与实例介绍
  9. python调用libvirt_通过python获取kvm虚拟机的监控信息(基于libvirt API)
  10. Linux系统语言教程,Linux操作系统基础及语言基础教程-麦可网张凌华