UVa1408/LA4018 Flight Control

news/2025/7/8 15:29:35

UVa1408/LA4018 Flight Control

  • 题目链接
  • 题意
  • 分析
  • AC 代码

题目链接

  本题是2007年icpc亚洲区域赛成都赛区的F题

题意

  有一个N行M列的数组(1 ≤ N ≤ 50, 1 ≤ M ≤ 9)记录机场各个航班的飞行传感数据,其每个元素都是整数。如果某元素小于等于0,则其一定不是航班的飞行数据。如果某个元素大于0,则其可能是一个航班的飞行数据,也可能和所在行(或列)连续严格递增(或严格递减)的子序列一起构成一个航班的飞行数据。不同航班的传感数据不能重叠,求数组最少代表的航班数。

分析

  首先想到利用轮廓线动态规划处理覆盖问题的思路来求解,状态是4进制M位:每一位代表所在航班往上、下、左、右飞行。那么状态转移一共 4 M ∗ M ∗ N 4^M*M*N 4MMN次,最高达到 10 8 10^8 108(117964800),这种原始做法会超过3s限时。

  对取值为左、右的状态位,可以发现仅仅在其为状态的末尾时才有可能影响当前的状态转移决策,末尾之前的那些状态位取值为左、右时无法影响当前的状态转移决策。因此,可以将状态定义成3进制(上、下、水平)再加上末尾是否为左右即可。这时状态转移一共 2 ∗ 3 M ∗ M ∗ N 2*3^M*M*N 23MMN次,最高达到 10 7 10^7 107(17714700),3s内应该能过,写出此版本的代码验证发现大约运行2s:

#include <iostream>
#include <cstring>
using namespace std;#define M 9
#define N 50
#define T 39366
int a[N][M], d[2][T], p[] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683}, m, n, kase = 0;void solve() {memset(d[0], 0, sizeof(d[0]));int c = 0, t = p[m]<<1, r = p[max(m-1, 0)], ans = m*n;for (int i=0; i<n; ++i) for (int j=0; j<m; ++j, c^=1) {int v, f = i ? a[i-1][j] : 0, l = j ? a[i][j-1] : 0;cin >> v; a[i][j] = v = max(v, 0); memset(d[c^1], 1, sizeof(d[0]));for (int k=0; k<t; ++k) {int h = (k>>1)/r, s = (k>>1)%3, e = (k>>1)%r, b = k&1;int &w = d[c^1][6*e], &x = d[c^1][6*e+1], &y = d[c^1][6*e+2], &z = d[c^1][6*e+4];w = min(w, d[c][k] + (v && (!l || s || l>=v || b)));x = min(x, d[c][k] + (v && (!l || s || l<=v || !b)));y = min(y, d[c][k] + (v && (!f || h!=1 || f>=v)));z = min(z, d[c][k] + (v && (!f || h!=2 || f<=v)));}}for (int i=0; i<t; ++i) ans = min(ans, d[c][i]);cout << "Case " << ++kase << ": " << ans << endl;
}int main() {while (cin >> n >> m && (m || n)) solve();return 0;
}

  更进一步,由于利用行内连续3个元素(或者列内连续3个元素)可以判定能否水平(或者竖直)飞行以及飞行方向,那么状态可以用未定(代表当前位置为新航班)、水平、竖直这样的3进制来表示。状态转移一共 3 M ∗ M ∗ N 3^M*M*N 3MMN次,时间又缩短一半,并且可以利用备忘录dp来进一步优化时间。这种方法要注意一点:如果正上方位置取值是未定,而右上取值是水平,则当前位置决策时不能取到竖直

AC 代码

#include <iostream>
#include <cstring>
using namespace std;#define M 9
#define N 50
#define T 19683
int a[N][M], d[N][M][T], p[] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, T}, m, n, kase = 0;bool check(int a, int b, int c) {if (!a || !b || !c || a==b || b==c) return false;return a < b ? b < c : b > c;
}int dp(int i, int j, int s) {if (i == n) return 0;if (j == m) return dp(i+1, 0, s);if (d[i][j][s] >= 0) return d[i][j][s];int &r = d[i][j][s], t = i ? a[i-1][j] : 0, l = j ? a[i][j-1] : 0, h = s / p[m-1], b = s % 3, c = a[i][j];r = dp(i, j+1, s % p[m-1] * 3) + (c != 0);if (c && l && ((!b && c != l) || (b==1 && check(a[i][j-2], l, c))))r = min(r, dp(i, j+1, s % p[m-1] * 3 + 1));if (c && t && ((!h && c != t && (j+1<m ? s/p[m-2]%3 : 0) != 1) || (h==2 && check(a[i-2][j], t, c))))r = min(r, dp(i, j+1, s % p[m-1] * 3 + 2));return r;
}void solve() {memset(d, -1, sizeof(d));for (int i=0; i<n; ++i) for (int j=0; j<m; ++j) cin >> a[i][j], a[i][j] = max(a[i][j], 0);cout << "Case " << ++kase << ": " << dp(0, 0, 0) << endl;
}int main() {while (cin >> n >> m && (m || n)) solve();return 0;
}

https://dhexx.cn/news/show-5542236.html

相关文章

深入解析协程:高并发编程的轻量级解决方案

在当今高并发编程领域&#xff0c;协程&#xff08;Coroutine&#xff09; 已成为提升系统性能的关键技术。本文将深入探讨协程的核心原理、实现机制及实际应用场景&#xff0c;帮助开发者掌握这一轻量级并发模型。 一、协程的本质与演进 协程是用户态轻量级线程&#xff0c;由…

架构优化——submodule转为subtree

文章目录 背景subtree优势submodule切换到subtree脚本subtree使用切开发分支推送代码同步代码 背景 submodule过多&#xff0c;目前20个submodule需要切出20个分支&#xff0c;查看提交记录、切分支等使用起来麻烦。 团队深受困扰&#xff01; subtree优势 继承submodule的…

Conda 修改镜像源:加速包下载与解决连接问题

Conda 修改镜像源&#xff1a;加速包下载与解决连接问题 在使用 Conda&#xff08;Anaconda/Miniconda&#xff09;进行 Python 环境管理时&#xff0c;默认的官方源&#xff08;defaults 和 conda-forge&#xff09;通常位于国外&#xff0c;下载速度可能较慢&#xff0c;甚至…

【Leetcode】每日一题 —— No.2966

LeetCode 2966. 将数组分成差值不超过 k 的长度为 3 的子数组 原题链接&#xff1a;LeetCode CN - Divide Array Into Arrays With Max Difference 题目描述 给你一个整数数组 nums 和一个正整数 k。 你需要将这个数组划分为 n / 3 个长度为 3 的子数组。每个子数组必须满足&…

如何使用ChatGPT快速完成一篇论文初稿?

2小时写完论文初稿&#xff0c;学境思源&#xff0c;听起来是不是有点不真实&#xff1f;一键生成论文初稿&#xff01;但如果你有一个清晰的框架、良好的写作节奏&#xff0c;acaids.com。再配合像ChatGPT这样的写作助手——真的可以做到。 这篇文章就是手把手告诉你&#xf…

【计算机常识】--docker入门+docker desktop的使用(一)

摘要 docker官网&#xff1a; Docker: Accelerated Container Application Development docker desktop官网&#xff1a;http://hub.docker.com/ docker文档官网&#xff1a;Docker Docs Docker是基于Go语言实现的云开源项目。 Docker的主要目标是&#xff1a;Build, Ship…

聊一聊显卡这个东西

聊一聊显卡这个东西 计算机显卡&#xff1a;数字世界的视觉引擎 在计算机的众多硬件中&#xff0c;显卡堪称 “视觉魔法师”&#xff0c;它承担着将数字信号转化为绚丽图像的重任&#xff0c;无论是畅玩 3A 大作时身临其境的游戏画面&#xff0c;还是专业设计软件中细腻逼真的…

Redission实现的分布式锁的可重入性

Redisson 分布式锁在 Redis 中存储可重入状态所使用的 Hash 结构&#xff0c;并通过示例说明。 核心数据结构 Key: 锁的名称。例如&#xff1a;"myLock"。数据类型: Hash (Redis HSET / HGET / HINCRBY 操作的对象)。Hash Field (字段名): 客户端唯一标识符。格式通…

new()和new[]有什么区别?

new()和new[]有什么区别&#xff1f; 1、new[]的使用较为简单&#xff0c;一般用来开辟内存并初始化&#xff0c;常用于设置动态数组的大小。 int a[]; //声明动态数组 initial begina new[3]; //为动态数组分配3个元素foreach (a[i]) a[i] i; //元素初始化 end2、new…

如何高效实现公司文件管理

要实现公司文件管理的高效&#xff0c;企业应聚焦统一文件规范、部署文档管理系统、强化权限控制、推动协同编辑、实施定期清理、推进文化建设、引入可视化分析。其中&#xff0c;统一文件规范是文件高效管理的基础。若缺乏清晰的命名规则与分类体系&#xff0c;即便配备了先进…