1031D - Minimum path

本文解析了1031D-Minimum path问题,通过动态规划确定最少改变次数使路径字典序最小,再利用BFS寻找最优路径,最后通过DFS逆向输出答案。适用于算法竞赛和路径优化问题。

1031D - Minimum path

题目描述

传送门

题目大意

给你一个 n × n n \times n n×n的只有小写字母的字符矩阵,你要从 1 , 1 1,1 1,1走到 n , n n,n n,n,只能往下,往右走,同时你可以改变这个矩阵中的 k k k个字符,问你走到 n , n n,n n,n所经过的路径的最小字典序是多少。
1 ≤ n ≤ 2000 1 \le n \le 2000 1n2000

Solution

比赛的时候最后5分钟才过去,保我上蓝QwQ

  • 首先这道题要求字典序最小,所以我们改变这个矩阵中的字符,一定是把不是 a a a的字符改成 a a a,而且我们走一条路径的时候,一定是把所有机会全用到(如果 k k k过大就可以全是 a a a),并且尽可能地要让前面变成 a a a
    所以我们设 f [ i ] [ j ] f[i][j] f[i][j]表示从 1 , 1 1,1 1,1走到 i , j i,j i,j全走 a a a至少要改变多少次,由于只能向下和向右走,所以 f [ i ] [ j ] f[i][j] f[i][j]只可能从 f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] f[i - 1][j], f[i][j - 1] f[i1][j],f[i][j1]转移过来。DP复杂度 O ( n 2 ) O(n^2) O(n2)
  • 之后,我们把 f [ i ] [ j ] ≤ k f[i][j] \le k f[i][j]k点找出来,找出所有走得最远的点,作为接下来 B F S BFS BFS的起点(特别地,如果 k = 0 k = 0 k=0就需要把 1 , 1 1,1 1,1选出来当作起点)。
  • 进行BFS,我们看图说话:
    在这里插入图片描述
    假设红色的点为现在的起点,那么黄色箭头表示现在的的起点能前往的格子,我们找出现在能到达的格子中最小的字符,然后把带有最小字符的格子(也就是上图中的蓝色格子)存起来(同时给这个格子打一个标记,说明这个格子可以当作答案的一步),当作下一次的起点,重复上树的操作知道到达 n , n n,n n,n,由于我们每进行一次操作,都相当于走了一步,所以最多进行 n n n次这样的操作。
    在这里插入图片描述
    看起来似乎状态是呈指数级增长的,BFS会爆掉,但实际上,我们发现,最坏的情况就是上图的情况,但是每层的情况数最多也只会达到 n n n个,所以,BFS的复杂度为 O ( n 2 ) O(n^2) O(n2)
  • 至于输出答案,我们可以从 n , n n,n n,n进行DFS,这个点上面或者左面哪一个点被打过标记,就往那边走,一直走到最初的起点。
    之后输出 a a a和找到的路径即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

const int maxn = 2e3 + 7;

class Solution{
private :
    int n, k, cnt;
    char s[maxn][maxn];
    int f[maxn][maxn];
    bool vis[maxn][maxn];
    
    char ans[maxn * 2];
    int tot;

    struct Node{
        int x, y;

        Node (int x, int y) :
            x(x),
            y(y) {}
    };
    
    int now, last;
    std :: queue<Node> q[2], tmp;

    void Make() {
        for (register int i = 1; i + cnt < n + n; i++) {
            char z = 'z' + 1;
            while (!q[last].empty()) {
                Node nd = q[last].front();
                tmp.push(nd);
                q[last].pop();
                if (nd.x < n) {
                    z = std :: min(z, s[nd.x + 1][nd.y]);
                }
                if (nd.y < n) {
                    z = std :: min(z, s[nd.x][nd.y + 1]);
                }
            }
            while (!tmp.empty()) {
                Node nd = tmp.front();
                tmp.pop();
                if (nd.x < n) {
                    if (s[nd.x + 1][nd.y] == z && !vis[nd.x + 1][nd.y]) {
                        vis[nd.x + 1][nd.y] = 1;
                        q[now].push(Node(nd.x + 1, nd.y));
                    }
                }
                if (nd.y < n) {
                    if (s[nd.x][nd.y + 1] == z && !vis[nd.x][nd.y + 1]) {
                        vis[nd.x][nd.y + 1] = 1;
                        q[now].push(Node(nd.x, nd.y + 1));
                    }
                }
            }
            std :: swap(now, last);
        }
    }
    
    void DFS(int x, int y) {
    	if (x <= 0 || y <= 0) {
    		return;
		}
    	if (x + y == cnt) {
    		return;
		}
		ans[++tot] = s[x][y];
		if (vis[x - 1][y]) {
			DFS(x - 1, y);
		} else {
			DFS(x, y - 1);
		}
	}
    
public :
    Solution() {
        now = 1;
        last = 0;
        Get();
        Solve();
    }

    void Get() {
        scanf("%d %d", &n, &k);
        for (register int i = 1; i <= n; i++) {
            scanf("%s", s[i] + 1);
        }
    }

    void Solve() {
        memset(f, 0x3f, sizeof(f));
        f[1][1] = s[1][1] == 'a' ? 0 : 1;
        for (register int i = 1; i <= n; i++) {
            for (register int j = 1; j <= n; j++) {
            	if (i == 1 && j == 1) {
            		continue;
				}
                f[i][j] = std :: min(f[i - 1][j], f[i][j - 1]);
                if (s[i][j] != 'a') {
                    f[i][j]++;
                }
            }
        }
        for (register int i = 1; i <= n; i++) {
            for (register int j = 1; j <= n; j++) {
                if (f[i][j] <= k && i + j > cnt) {
                    cnt = i + j;
                }
            }
        }
        for (register int i = 1; i <= n; i++) {
            for (register int j = 1; j <= n; j++) {
                if (i + j == cnt && f[i][j] <= k) {
                    vis[i][j] = 1;
                    q[last].push(Node(i, j));
                }
            }
        }
        if (q[last].empty()) {
        	vis[1][1] = 1;
        	q[last].push(Node(1, 1));
		}
        Make();
        DFS(n, n);
        for (register int i = 1; i < cnt; i++) {
        	putchar('a');
		}
		for (register int i = tot; i >= 1; i--) {
			putchar(ans[i]);
		}
		putchar('\n');
    }
};
Solution sol;

int main() {}
<think>嗯,用户现在遇到了CMake导入Boost::headers时路径不存在的问题。我需要仔细分析可能的原因和解决方案。首先,CMake在查找Boost库时,可能会因为安装路径不在默认搜索路径中导致失败。用户可能没有正确设置BOOST_ROOT或者Boost_DIR环境变量,或者没有指定正确的架构。 接下来,我需要回忆CMake的FindBoost模块的工作机制。FindBoost会搜索特定的路径,如果Boost安装在非标准位置,用户必须明确指定路径。此外,区分静态库和动态库也可能影响路径的查找,特别是在Windows上,可能需要指定Boost_USE_STATIC_LIBS。 另外,用户可能没有正确调用find_package,或者版本号不匹配。例如,如果用户安装的是Boost 1.80,但CMake脚本中指定了1.79,就会导致找不到。同时,生成器选择也可能有问题,比如使用Visual Studio时需要指定架构参数-A x64。 还有可能的问题包括Boost头文件未正确安装,或者路径中包含空格导致解析错误。需要建议用户检查Boost的安装情况,并确保路径中没有特殊字符。 最后,可能需要指导用户如何通过设置缓存变量或者使用-D选项在配置时传递参数,确保CMake能够正确找到Boost的包含路径和库文件。同时,引用提到的CMAKE_CXX_STANDARD和C++标准设置也可能相关,需要确认用户的项目配置是否兼容Boost的要求。</think>### CMake导入Boost::headers报错解决方案 在CMake项目中导入Boost::headers时出现路径不存在的问题,通常由以下原因导致: 1. **Boost未正确安装** - 验证Boost是否通过源码编译或包管理器安装 - 检查安装路径是否包含头文件目录(如`boost/version.hpp`) ```cmake # 强制指定Boost根目录 set(BOOST_ROOT "C:/local/boost_1_81_0") # Windows示例 ``` 2. **CMake搜索路径配置** - 设置环境变量或CMake变量指定Boost位置 ```cmake # 在CMakeLists.txt开头添加 set(BOOST_INCLUDEDIR "${BOOST_ROOT}/include") set(BOOST_LIBRARYDIR "${BOOST_ROOT}/lib") ``` 3. **架构不匹配问题**(常见于Windows) - 显式指定库架构 ```cmake # 对于Visual Studio生成器 set(Boost_ARCHITECTURE "-x64") ``` 4. **组件未正确声明** - 确保find_package包含必要组件 ```cmake find_package(Boost 1.81 REQUIRED COMPONENTS headers) target_link_libraries(your_target PRIVATE Boost::headers) ``` 完整配置示例: ```cmake cmake_minimum_required(VERSION 3.12) project(boost_test) set(BOOST_ROOT "D:/boost_1_81_0") # 实际安装路径 set(Boost_USE_STATIC_LIBS ON) # 如果使用静态库 find_package(Boost 1.81 REQUIRED COMPONENTS headers) add_executable(main main.cpp) target_link_libraries(main PRIVATE Boost::headers) ``` 验证步骤: 1. 检查`Boost_INCLUDE_DIRS`变量是否包含正确路径 2. 查看CMake输出中是否显示`Found Boost headers: 1.81.0` 3. 确保`CMAKE_PREFIX_PATH`包含Boost安装目录
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值