P1018 乘积最大
题意:有一个字符串s(|s|<=40),给k(k<=6)个乘号,问怎样组合得到的数字最大。
解法:这题不难!只是太复杂了!40位的数据的话,只能用高精度了,做法是dp,先预处理出qj[i][j] (i≤j)表示s字符串位置在i-j的子串,dp[i][j]表示以i为结尾用了j个乘号得到的最大数字,那么转移方程就是 d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ x ] [ j − 1 ] ∗ q j [ x + 1 ] [ i ] ) dp[i][j]=max(dp[i][j], dp[x][j-1]*qj[x+1][i]) dp[i][j]=max(dp[i][j],dp[x][j−1]∗qj[x+1][i]),注意一下边界问题就可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int ne[4][2] = {
1, 0, 0, 1, -1, 0, 0, -1};
const int N = 50;
int n, k;
string s;
string max(string a, string b) {
if(a.size() != b.size()) return a.size() < b.size() ? b : a;
return a < b ? b : a;
}
//高精度加法
string add(string a, string b) {
string res = "", r = "";
int jw = 0, l1 = a.size(), l2 = b.size();
int p1 = l1-1, p2 = l2-1, mid;
while(p1 >= 0 && p2 >= 0) {
mid = a[p1--]-'0'+b[p2--]-'0'+jw; jw = 0;
r = (mid%10)+'0';
res.insert(0, r);
if(mid >= 10) jw = mid/10;
}
while(p1 >= 0) {
mid = a[p1--]-'0'+jw; jw = 0;
r = (mid%10)+'0';
res.insert(0, r);
if(mid >= 10) jw = mid/10;
}
while(p2 >= 0) {
mid = b[p2--]-'0'+jw; jw = 0;
r = (mid%10)+'0';
res.insert(0, r);
if(mid >= 10) jw = mid/10;
}
if(jw) res.insert(0, "1");
return res;
}
//高精度乘法
string mul(string a, string b) {
string res = "", r1 = "", r;
int jw = 0, l1 = a.size(), l2 = b.size();
int mid, num_0 = 0;
for(int i = l2-1; i >= 0; --i) {
r1 = "";
for(int j = l1-1; j >= 0; --j) {
mid = (b[i]-'0')*(a[j]-'0')+jw; jw = 0;
r = (mid%10) + '0';
r1.insert(0, r);
if(mid >= 10) jw = mid / 10;
}
if(jw) {
r = jw + '0', r1.insert(0, r); jw = 0; }
for(int j = 0; j < num_0; ++j) r1.append("0");
++num_0;
res = add(res, r1);
}
return res;
}
string qj[N][N], dp[N][N];
int main() {
cin >> n >> k >> s;
int len = s.size();
for(int i = 0; i < len; ++i) for(int j = i; j < len; ++j)
qj[i][j] = s.substr(i, j-i+1);
//预处理
for(int i = 0; i < len; ++i) {
dp[i][0] = qj[0][i];
for(int j = 1; j <= k; ++j) dp[i][j] = "0";
}
//dp!
for(int i = 0; i < len; ++i) {
for(int j = 1; j <= k; ++j) {
for(int x = j-1; x < len; ++x) {
dp[i][j] = max(dp[i][j], mul(dp[x][j-1], qj[x+1][i]));
}
}
}
cout << dp[len-1][k] << endl;
return 0;
}