整数划分问题

题目链接  http://acm.nyist.net/JudgeOnline/status.php?pid=746

描述

暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷。。亲爱的你能帮帮他吗?

问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积

分析:设N为字符串S,设dp[i][j]为字符串从第0位到第i位中间加入j-1个乘号的最大值。

设字符串中第i位到第j位的数字为mul[i][j].

那么可以推出 dp[i][j] = max(dp[k][j-1] * mul[k+1][i]);

最后结果即求dp[s.size()-1][m];

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <string>
 5 #include <algorithm>
 6 using namespace std;
 7 int T;
 8 string s;
 9 long long m;
10 long long  mul[25][25], dp[25][25];
11 int main(){
12     scanf("%d", &T);
13     while(T--){
14         cin>>s; cin>>m;
15         bool flag = false;
16         for(int i = 0; i < s.size(); i++){
17             for(int j = i; j < s.size(); j++){
18                 if(s[j] == '0') flag = true;
19                 if(i == j) mul[i][j] = s[j] -'0'; 
20                 else mul[i][j] = mul[i][j-1]*10 + s[j] - '0';
21             }
22         }
23         if(m == s.size() && flag == true){ //刚好分成n段且里面有个0. 
24             printf("0
"); continue;
25         }
26         memset(dp, 0, sizeof(dp));
27         for(int  i = 0; i < s.size(); i++){
28             dp[i][1] = mul[0][i];
29         }
30          
31         if(m == 1){
32             printf("%d
", dp[s.size()-1][1]); continue;
33         }
34         for(long long  cm = 2; cm <= m; cm++){             //枚举m是多少 
35             for(long long  i = cm-1; i < s.size(); i++){   //枚举到哪个位置 
36                 for(long long  k = cm-2; k < i; k++){
37                     dp[i][cm] = max(dp[i][cm], dp[k][cm-1]*mul[k+1][i]);
38                 }
39             }
40         }
41         cout<<dp[s.size()-1][m]<<endl;
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/titicia/p/4345390.html