|
发表于 2023-11-29 16:20:31
|
显示全部楼层
本楼为最佳答案
本帖最后由 柿子饼同学 于 2023-11-29 16:32 编辑
动态规划 , 设 f[ i ] 表示 和为 i 的正整数最大乘积
很显然 , 算 f[ i ] 的时候可以从 1 - i-1 枚举 j , 让 f[ i ] = max(f[ i ], f[ j ]*f[ i - j ])
这样就能算出来答案 , 即 f[1000]
初始化的时候让 f[ i ] = i , 就是先分出一个数情况的最大乘积
- #include <stdio.h>
- typedef long long ll;
- ll f[1005];
- ll max(ll a, ll b){
- if(a > b) return a;
- return b;
- }
- int main(){
- for(int i = 1; i <= 1000; i++){
- f[i] = i;
- }
- for(int i = 1; i <= 1000; i++){
- for(int j = 1; j < i; j++){
- f[i] = max(f[i], f[j]*f[i - j]);
- }
- }
- printf("%lld", f[1000]);
-
- return 0;
- }
复制代码
如果你想知道具体方案 , 可以另外开数组 r[a][0/1] 表示 和为 a 的最大乘积是由 r[a][0] 和 r[a][1] 这两个和推出来的 , 递归输出即可
- #include <stdio.h>
- typedef long long ll;
- ll f[1005];
- int r[1005][2];
- void Print(int pos){
- // 边界: r[pos][0] == pos, 即 pos 不能分成另外两个数时, 输出并返回
- if(r[pos][0] == pos){
- printf("%d ", pos);
- return ;
- }
- // 否则递归输出 pos 可以分成的两个和
- Print(r[pos][0]);
- Print(r[pos][1]);
- }
- int main(){
- for(int i = 1; i <= 1000; i++){
- f[i] = i;
- r[i][0] = i; // 每个数先记下来最优解就是自己
- }
- for(int i = 1; i <= 1000; i++){
- for(int j = 1; j < i; j++){
-
- // 如果乘积比 f[ i ] 大就记下来
- if(f[j]*f[i - j] > f[i]){
- f[i] = f[j]*f[i - j];
- // 记录 i 分成 j 和 i-j 是最优解
- r[i][0] = j, r[i][1] = i - j;
- }
- }
- }
- printf("%lld", f[1000]);
- Print(1000);
-
- return 0;
- }
复制代码 |
|