http://uoj.ac/problem/107

设\(f(l,r,i,j)\)表示\([l,r]\)中的机器人聚集到\((i,j)\)需要花的最小操作数。

\(f(l,r,i,j)=\min\left\{\begin{array}{rcl}
f(l,k,i,j)+f(k+1,r,i,j)\\
f(l,r,i',j'),(i',j')\rightarrow(i,j)\end{array}\right.\)

斯坦纳树的模型,对于每个\([l,r]\)的状态,处理完第一行后再跑一遍双队列广搜处理第二行。

用基数排序优化,时间复杂度\(O(n^3+n^2hw)\)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 503;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1}; struct data {
int x, y;
data (int _x = 0, int _y = 0) : x(_x), y(_y) {}
} to[N][N][4]; bool vis[N][N][4];
char s[N][N];
int f[10][10][N][N], n, w, h; data work(int x, int y, int tmp) {
if (vis[x][y][tmp]) return to[x][y][tmp];
vis[x][y][tmp] = true;
if (s[x][y] == 'A') (++tmp) &= 3;
if (s[x][y] == 'C') (--tmp) &= 3;
if (s[x + dx[tmp]][y + dy[tmp]] == 'x')
return data(x, y);
else
return to[x + dx[tmp]][y + dy[tmp]][tmp] = work(x + dx[tmp], y + dy[tmp], tmp);
} int tot = 0, l, r, id[N * N];
data q1[N * N], q2[N * N], tt; template <typename T> void check_min(T &a, T b) {if (b < a) a = b;}
template <typename T> void check_max(T &a, T b) {if (b > a) a = b;} bool cmp(data A, data B) {return f[l][r][A.x][A.y] < f[l][r][B.x][B.y];} int c[N * N * 20]; void BFS() {
// stable_sort(q1 + 1, q1 + tot + 1, cmp);
int mx = 0, num;
for (int i = 1; i <= tot; ++i) if ((num = f[l][r][q1[i].x][q1[i].y]) != 1010580540) check_max(mx, num);
memset(c, 0, sizeof(int) * (mx + 2));
for (int i = 1; i <= tot; ++i) {
num = f[l][r][q1[i].x][q1[i].y];
if (num != 1010580540) ++c[num];
else ++c[mx + 1];
}
for (int i = 1; i <= mx + 1; ++i) c[i] += c[i - 1];
for (int i = tot; i >= 1; --i) {
num = f[l][r][q1[i].x][q1[i].y];
if (num == 1010580540) num = mx + 1;
id[c[num]--] = i;
}
int head = 1, tail = 0, tmp = 1, x, y, x2, y2;
while (head <= tail || tmp <= tot) {
x = q2[head].x; y = q2[head].y;
x2 = q1[id[tmp]].x; y2 = q1[id[tmp]].y;
if (head <= tail && tmp <= tot && f[l][r][x][y] < f[l][r][x2][y2] || tmp > tot) ++head;
else ++tmp, x = x2, y = y2;
for (int d = 0; d < 4; ++d) {
tt = to[x][y][d];
if (tt.x == 0) continue;
if (f[l][r][tt.x][tt.y] > f[l][r][x][y] + 1) {
f[l][r][tt.x][tt.y] = f[l][r][x][y] + 1;
q2[++tail] = tt;
}
}
}
} int main() {
scanf("%d%d%d", &n, &w, &h); memset(f, 60, sizeof(f)); for (int i = 1; i <= h; ++i)
scanf("%s", s[i] + 1);
for (int i = 1; i <= h; ++i) s[i][0] = s[i][w + 1] = 'x';
for (int i = 1; i <= w; ++i) s[0][i] = s[h + 1][i] = 'x';
for (int i = 1 ; i <= h; ++i)
for (int j = 1; j <= w; ++j)
if (s[i][j] != 'x')
for (int dt = 0; dt < 4; ++dt)
to[i][j][dt] = work(i, j, dt); for (int i = 1; i <= h; ++i)
for (int j = 1; j <= w; ++j) q1[++tot] = data(i, j); bool flag;
for (int i = n; i >= 1; --i) {
flag = false;
for (int ii = 1; ii <= h; ++ii) {
for (int jj = 1; jj <= w; ++jj)
if (s[ii][jj] == '0' + i) {
f[i][i][ii][jj] = 0;
flag = true;
break;
}
if (flag) break;
}
l = r = i; BFS();
for (int j = i + 1; j <= n; ++j) {
for (int k = i; k < j; ++k)
for (int ii = 1; ii <= h; ++ii)
for (int jj = 1; jj <= w; ++jj)
check_min(f[i][j][ii][jj], f[i][k][ii][jj] + f[k + 1][j][ii][jj]);
l = i; r = j; BFS();
}
} int ans = 0x7fffffff;
for (int i = 1; i <= h; ++i)
for (int j = 1; j <= w; ++j)
check_min(ans, f[1][n][i][j]);
printf("%d\n", ans == 1010580540 ? -1 : ans);
return 0;
}

【UOJ #107】【APIO 2013】ROBOTS的更多相关文章

  1. 【UOJ #108】【APIO 2013】TOLL

    http://uoj.ac/problem/108 好神的一道题啊. 原图边权互不相同是重点! 如果有一个点集,有两组边集,要求这两组边集的并集的最小生成树,可以对两组边集分别求一下最小生成树构成新的 ...

  2. 【UOJ】67 新年的毒瘤 &【BZOJ】1123 BLO

    [UOJ 67] 题目链接: 传送门 题解: 第一眼很懵逼……这什么鬼. 思考什么点复合条件……(o(>﹏<)o 1.树,也就是说还剩n-2条边,等价于要删去一个度数为m-n+2的点. 2 ...

  3. 【UOJ#236】[IOI2016]railroad(欧拉回路,最小生成树)

    [UOJ#236][IOI2016]railroad(欧拉回路,最小生成树) 题面 UOJ 题解 把速度看成点,给定的路段看成边,那么现在就有了若干边,然后现在要补上若干边,以及一条\([inf,\) ...

  4. 【UOJ#177】欧拉回路

    [UOJ#177]欧拉回路 题面 UOJ 题解 首先图不连通就没啥好搞的了. 对于无向图而言,每个点度数为偶数. 对于有向图而言,每个点入度等于出度. 然后就是一本通上有的做法,直接\(dfs\)一遍 ...

  5. 【UOJ#311】【UNR #2】积劳成疾(动态规划)

    [UOJ#311][UNR #2]积劳成疾(动态规划) UOJ Solution 考虑最大值分治解决问题.每次枚举最大值所在的位置,强制不能跨过最大值,左右此时不会影响,可以分开考虑. 那么设\(f[ ...

  6. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  7. 【UOJ#246】套路(动态规划)

    [UOJ#246]套路(动态规划) 题面 UOJ 题解 假如答案的选择的区间长度很小,我们可以做一个暴力\(dp\)计算\(s(l,r)\),即\(s(l,r)=min(s(l+1,r),s(l,r- ...

  8. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

  9. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

随机推荐

  1. vue-cli使用说明

    一.安装npm install -g vue-cli 推荐使用国内镜像 先设置cnpm npm install -g cnpm --registry=https://registry.npm.taob ...

  2. CSS实现箭头效果

    有时候网页中使用箭头以增强效果,一般的做法是使用图片,今天我们使用CSSCSS来实现“箭头效果”,使用CSS我们必须兼容所有浏览器(IE6.7.8.9.10.+),Chrome,Firefox,Ope ...

  3. 转: oracle中schema指的是什么?

    看来有的人还是对schema的真正含义不太理解,现在我再次整理了一下,希望对大家有所帮助. 我们先来看一下他们的定义:A schema is a collection of database obje ...

  4. 宝塔Linux面板新手安装教程【转】

    一.使用远程连接软件 (如 Putty.XShell) 连接你的Linux服务器,本教程以 Putty 为例. 1.动 Putty.exe 程序,进入 Putty 主界面. 2.在 Host Name ...

  5. python使用requests模块模拟登陆知乎

    from bs4 import BeautifulSoup import requests import time def captcha(captcha_data): with open(" ...

  6. socket 开发 - 那些年用过的基础 API

    ---------------------------------------------------------------------------------------------------- ...

  7. VS2015_动态链接库学习

    非MFC动态链接库 创建一个名为ex1的Win32项目 创建一个DLL项目,保留预编译的头文件   默认文件 创建完成项目之后,包含几个默认的文件   stdafx.h文件用于包含标准系统包含的头文件 ...

  8. bash: composer: command not found

    下载composer到本地:curl -sS https://getcomposer.org/installer | php 移动至系统服务:sudo mv composer.phar /usr/bi ...

  9. chm转换为html文件

    在Windows下chm转换为html的超简单方法(反编译CHM文件的方法) 通过调用Windows命令,将chm 文件转换为html 文件. 方法: 命令行(cmd),输入hh -decompile ...

  10. C# 多线程多文件批量下载---子线程中更新UI 实例

    代码1: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;usi ...