整数划分问题
题目链接 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\n"); 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\n", 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 }