关于#c++#的问题,请各位专家解答!

在弟弟那里发现了一道很中二的题……然后发现我俩都不怎么会就来试试提问

克索图斯为了获得“战神”称号即将前往终焉之地进行试炼,终焉之地是一座 N×N 的古战场(N≤9),里边充斥着各种怪物,克索图斯只有x点能量值,每击败一只怪物需要消耗1点能量值,能量值耗尽还未抵达终点则试炼失败,方格中的数字表示该位置怪物的数量,数字为0表示该位置不存在怪物。如图所示,克索图斯需要从图的右上角的起点A点出发,可以向下行走,也可以向左走,直到到达左下角的终点B点。在走过的路上,他需要击败沿途的所有怪物(经过的方格中的数字将变为0)。为了让“战神“的称号当之无愧,克索图斯会选择怪物最多的路径前进。

img

输入
第一行包含一个正整数X(X≤1000),表示克索图斯具有的能量值。
第二行包含一个正整数N(N≤9),表示终焉之地的大小为N×N。
接下来的每行有三个整数,前两个表示位置,第三个数为该位置上存在的怪物数量。一行单独的0表示输入结束。

输出
若能量值能够支撑克索图斯从A到B,只需输出一个整数,表示该路径上一共击败的怪物数量;
若能量值不足以克索图斯从A到B,则试炼失败,输出“no“。

样例1
输入
25
6
1 1 12
2 3 6
3 5 7
4 2 11
5 5 19
3 6 4
6 3 15
4 4 7
0 0 0
输出
no
样例2
输入
60
6
1 1 12
2 3 6
3 5 7
4 2 11
5 5 19
3 6 4
6 3 15
4 4 7
0 0 0
输出
45

这是一道搜索问题。克索图斯需要通过搜索来找到所有可行的路径,并在“可通”中选择怪物数量最多的路径。具体实现时,可以在搜索过程中记录每条路径已经击败的怪物数量,如果克索图斯到达了终点,则与当前最多击败的怪物数量进行比较并更新。搜索时需要注意一些剪枝策略,比如如果当前路径的击败怪物数量已经小于等于当前最多的怪物数量,则可以直接返回而无需继续搜索。

关键点:

  • 可行路径:路径上每个位置的怪物数量之和不能大于克索图斯的能量值。
  • 正确性:搜索的路径中,对于每个位置,只有唯一一种途径到达它,因为每个位置上的怪物数量只能被击败一次。
  • 剪枝策略:如果当前路径的击败怪物数量已经小于等于当前最多的怪物数量,则可以直接返回而无需继续搜索。

时间复杂度分析

搜索的时间复杂度取决于搜索树的大小,即所有可行路径的数量。在最坏情况下,克索图斯需要穿过所有的位置,因此搜索树大小为 O(2^{(N-1)}),时间复杂度为 O(2^{(N-1)})。实际上,由于有剪枝策略,绝大多数路径不会被搜索,因此搜索时间会远比最坏情况低。

参考代码

Python 3:

nrg = int(input())  # 克索图斯具有的能量值
N = int(input())    # 终焉之地的大小

# 搜索函数,从(x, y)出发,已经击败怪物数量为count,搜索到达终点的路径上最多可击败的怪物数量
def dfs(x, y, count):
    if x == N - 1 and y == 0:  # 到达终点
        return count + board[x][y]  # 将当前位置的怪物数量计入击败的总数
    if count + board[x][y] > max_nrg:  # 当前路径的估计击败怪物数量已经大于克索图斯的能量值
        return -1  # 直接返回一个无效的结果
    if count + board[x][y] <= best_count[x][y]:  # 剪枝:当前路径的击败怪物数量不大于已找到的最优解,没必要继续搜索
        return -1
    best_count[x][y] = count + board[x][y]  # 更新(x, y)的最优解
    res = -1  # 初始化结果
    for dx, dy in [(1, 0), (0, -1)]:  # 只能向下或向左移动
        nx, ny = x + dx, y + dy
        if 0 <= nx < N and 0 <= ny < N and board[nx][ny] > 0:  # 判断下一步是否可行
            tmp = board[nx][ny]  # 先记录下当前位置的怪物数量
            board[nx][ny] = 0    # 将怪物数量设为0,表示克索图斯已经击败它
            ret = dfs(nx, ny, count + tmp)  # 递归搜索
            if ret >= 0:  # 如果搜索到了合法的结果
                if res == -1:  # 如果res还没有被初始化
                    res = ret  # 直接赋值
                else:
                    res = max(res, ret)  # 取两种结果中怪物数量最多的那一种
            board[nx][ny] = tmp  # 恢复原来的怪物数量
    return res

max_nrg = nrg  # 克索图斯还没有消耗能量值,因此最多可以消耗nrg个能量
board = []  # 表示每个位置的怪物数量
best_count = [[-1] * N for _ in range(N)]  # best_count[x][y]表示已知的从(x, y)出发能够击败的最多怪物数量
for i in range(N):
    row = [0] * N
    while True:
        x, y, k = map(int, input().split())
        if x == 0 and y == 0 and k == 0:
            break
        row[x-1] = k
    board.append(row)

count = dfs(0, N-1, 0)  # 从起点(0, N-1)开始搜索
if count == -1:
    print("no")
else:
    print(count)

该代码的时间复杂度是指数级别的 ,请勿在复杂测试数据下尝试。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7521356
  • 除此之外, 这篇博客: 单素数判断(根号n后再优化)和俄罗斯农民乘法(带证明),以及埃筛的证明中的 简单解释下普遍大家都知道的(给新手),就是为啥只到根号n。最开始其实终止条件是到n/2的,很简单嘛,因为n/2之后不可能存在n的因子,因为最小的因子2乘上一个任何一个大于n/2的数肯定比n大,所以之后不存在因子。那为啥能筛到根号n呢,是因为根号n的平方是n本身,根号n后面如果存在n的因子a,那么一定能在n之前找到n/a这个因子,只要有因子就不是素数了,所以没必要反复筛,前面筛完就已经知道不是素数了 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    #include<bits/stdc++.h>
    using namespace std;
    int main() 
    {
    	int n;
    	cin>>n;
    	if(n==2||n==3)
    	{
    		cout<<"是素数";
    	}
    	else if(n%6!=1&&n%6!=5)
    	{
    		cout<<"不是素数";
    	}
    	else
    	{
    		for(int i=2;i*i<=n;i++)
    		{
    			if(!(n%i))
    			{
    				cout<<"不是素数" ;
    				return 0;
    			}
    		}
    		cout<<"是素数";
    	}
    }
    
  • 以下回答来自chatgpt:

    我需要题目的描述和样例输入输出才能进行解答。请将相关信息补充完整,谢谢!


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^