P1018 乘积最大
2016-11-07 19:53
232 查看
开始定义状态f[i][j][k]为[i,j)区间插入k个括号,使用记忆化搜索,但是成功爆栈,得到4个mle
#include <bits/stdc++.h> using namespace std; const int maxn = 45; int n, k, len; long long f[maxn][maxn][maxn]; char str[maxn]; int trans(int l, int r){ int x = 0; for(int i = l; i <= r; i++) { x = x * 10 + str[i] - '0'; } return x; } int dp(int left, int right, int cur) { if(cur <= 0) return f[left][right][cur] = trans(left, right); if(f[left][right][cur]) return f[left][right][cur]; int m, ans = 0; for(m = left; m <= right; m++) { for(int c = 0; c <= cur; c++) { ans = max(ans, dp(left, m, c) * dp(m+1, right, cur-c)); } } return ans; } int main() { cin >> n >> k; scanf("%s", str); len = strlen(str); memset(f, 0, sizeof(f)); cout << dp(0, len-1, k); }
后来重新思考(看题解),发现定义f[i][j]为前i个元素插入j个括号会更好,而且这样状态的转移就有了顺序,我们有方程:
f[i][j] = max(f[i][j], f[k][j-1]*trans(k,i)
这样,状态数O(n2),转移O(n)复杂度O(n3);
#include <bits/stdc++.h> using namespace std; const int maxn = 45; int n, k, len; long long f[maxn][maxn]; char str[maxn]; long long g[maxn][maxn]; long long trans(int l, int r){ if(g[l][r]) return g[l][r]; long long x = 0; for(int i = l; i <= r; i++) { x = x * 10 + str[i] - '0'; } return g[l][r] = x; } int main() { cin >> n >> k; scanf("%s", str); len = strlen(str); memset(f, 0, sizeof(f)); for(int i = 0; i < n; i++) { f[i][0] = trans(0, i); } for(int j = 1; j <= k; j++) { for(int i = 0; i < n; i++) { long long maxx = 0; for(int k = i; k >= j; k--) { maxx = max(maxx, f[k-1][j-1] * trans(k,i)); } f[i][j] = maxx; } } cout << f[n-1][k]; }
相关文章推荐
- P1018 乘积最大
- 洛谷—— P1018 乘积最大
- AC日记——乘积最大 洛谷 P1018
- 洛谷 P1018 乘积最大(NOIp2000提高组第二题)
- 洛谷 P1018 乘积最大
- 洛谷 P1018 [NOIP2000 T2] 乘积最大
- [NOIP2000] 提高组 洛谷P1018 乘积最大
- 【DP】洛谷 P1018 乘积最大
- (ssl1007)P1018 2000年分区联赛普级组之三 乘积最大
- P1018 乘积最大
- 洛谷 P1018 乘积最大
- P1018 乘积最大
- (ssl 1007)乘积最大
- 动态规划:乘积最大
- 编程之美之"子数组的最大乘积"
- 蓝桥杯算法训练 乘积最大
- NOJ 1017 乘积最大 (经典的区间dp)
- 最大K乘积问题:
- 最大子序乘积问题的分析
- 今日头条 2017年秋招编程题 :“最大乘积和”