1297. 猴子舞

本文介绍了一种使用动态规划算法解决特定数学问题的方法。通过构建dp数组,递归地找到将n个元素划分成多个环形组时的最大公约数最大化方案。文章提供了完整的C++实现代码,并分享了一些技巧,如使用long long类型来避免溢出。

TAG 动态规划

原本想用数学方法解, 构造了一下, 只能解出部分答案, 显然是有问题的....

我的经验就是, 对于这种"数学题", 一般是可以计算机的办法"暴力"解的, 暴搜或者dp吧..

先理清题意, 对于题目描述的图, 如果能保证图连通, 那就是一个环了. 因为连通性不作要求,所以实际上可以分为1个或多个环. 当然, 这里每个环至少包含2个"圈".

就是求把n分成若干份,使其的最大公约数最大.

dp[i][j]表示i个圈, 分成j个环

dp[i][j] = max{ dp[x][j-1] * (i-x) / gcd( dp[x][j-1], (i-x) }, (j-1)*2 <= x <= i-2

0.93s, 有点危险, 看了status, 有 0.00 sec的,应该是打表的吧, 有0.24 sec的, 难道有效率更高的方法? 我再想想..

hits: 注意用long long 这种推算类的题目结果经常很大, 还好这道还不用高精度...

// source code of submission 726741, Zhongshan University Online Judge System #include <stdio.h> #include <memory.h> const int N=250; long long dp[N][N/2]; long long gcd(long long x, long long y) { if ( x%y==0 ) { return y; } return gcd( y, x%y); } long long ans, tmp; int n; int main(int argc, char *argv[]) { memset(dp, 0, sizeof(dp) ); for (int i=0; i<N; ++i) { dp[i][0]=i+1; } for (int k=1; k<N/2; ++k) { for (int i=(k+1)*2-1; i<N; ++i) { dp[i][k]=dp[i-2][k-1]*2/gcd(dp[i-2][k-1], 2); for (int j=i-3; j>=k*2-1; --j) { tmp=dp[j][k-1]*(i-j)/gcd(dp[j][k-1], i-j); if ( dp[i][k]<tmp ) { dp[i][k]=tmp; } } } } while ( scanf("%d", &n), n!=0 ) { ans=dp[n-1][0]; for (int i=1; i<n/2; ++i) { if (ans<dp[n-1][i]) { ans=dp[n-1][i]; } } printf("%lld/n", ans); } return 0; }

猴子摘香蕉问题中,使用谓词逻辑表示法描述知识可以更清晰地表达猴子、箱子和香蕉之间的位置关系以及猴子的状态。以下是一个Python实现的示例代码: ```python # 全局变量用于记录步骤 step = 0 def print_step(action): global step step += 1 print(f"step: {step}, {action}") def monkey_go_to_box(monkey_pos, box_pos): if monkey_pos != box_pos: direction = "right" if box_pos > monkey_pos else "left" distance = abs(box_pos - monkey_pos) print_step(f"monkey从 {monkey_pos} 向 {direction} 走 {distance} 到达箱子处") return box_pos return monkey_pos def monkey_move_box(box_pos, banana_pos): if box_pos != banana_pos: direction = "right" if banana_pos > box_pos else "left" distance = abs(banana_pos - box_pos) print_step(f"monkey把箱子从 {box_pos} 向 {direction} 运 {distance} 到香蕉下方") return banana_pos return box_pos def monkey_get_banana(): print_step("monkey爬上箱子并摘到香蕉") def solve_monkey_banana(monkey_pos, banana_pos, box_pos): # 猴子走到箱子处 new_monkey_pos = monkey_go_to_box(monkey_pos, box_pos) # 猴子把箱子搬到香蕉下方 new_box_pos = monkey_move_box(box_pos, banana_pos) # 猴子摘香蕉 monkey_get_banana() # 读取输入的运行参数 (MonkeyPos, BananaPos, BoxPos) = input("请分别输入猴子、香蕉和箱子的位置坐标a、b、c(中间用英文逗号分隔):").split(",") # 假设 a=1, b=2, c=3 pos_mapping = {'a': 1, 'b': 2, 'c': 3} monkey = pos_mapping[MonkeyPos] banana = pos_mapping[BananaPos] box = pos_mapping[BoxPos] print('操作步骤如下:') solve_monkey_banana(monkey, banana, box) ``` 此代码通过定义几个函数来模拟猴子的不同动作,包括走到箱子处、移动箱子和摘香蕉。在`solve_monkey_banana`函数中,按照猴子摘香蕉的逻辑顺序调用这些函数。在输入位置时,使用字典`pos_mapping`将字母坐标转换为数字坐标以便于计算距离和方向。代码中考虑了猴子箱子、箱子香蕉的位置关系,只有当猴子和箱子位置不同时,猴子才会移动到箱子处;只有当箱子和香蕉位置不同时,猴子才会移动箱子到香蕉下方。最后猴子爬上箱子摘到香蕉。 [^1][^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值